关于Tomcat的Pipeline机制
来源:互联网 发布:l800清零软件 编辑:程序博客网 时间:2024/05/01 14:36
看了Tomcat的pipeline和valve的机制。试着写了一个简单的结构,记录一下。
pipeline--包含了改容器要唤醒的所有任务。每一个valve表示了一个特定的任务。容器的pipeline还有一个basic valve。valve可以自由添加一个或者多个。
类似于servlet过滤器,一个pipeline就像一个过滤链,每一个valve像一个过滤器。跟过滤器一样,一个valve可以操作传递给它的request和response方法。让一个阀门完成了处理,则进一步处理流水线中的下一个阀门,基本阀门总是在最后才被调用,但是会最先执行里面的方法。 一个容器可以实现pipeline接口。当容器的invoke方法被调用的时候,容器将会处理流水线中的阀门,并一个接一个的处理,直到所有的阀门都被处理完毕。
这个例子我们只有一个容器wrapper, servlet的封装类。它有一个servletClass属性来记录实际的servlet的名称。
HeaderLoggerValve和ClientIPLoggerValve是两个阀门,用来打印请求头和用户ip.
然后我们来看这个SimpleWrapper.
这个是谁呢,这个就是下面要说的SimplePipeline的basic valve,它是用来调用真实servlet的service方法的
SimpleWrapper里面有一个SimplePipeline,调simpleWrapper的invoke的话,就会调用它的invoke方法。SimplePipeline是这样的。
这个类里面有一个内部类SimplePipelineValveContext。它继承了ValveContext,里面很重要的一个方法是invokeNext.它是这样工作滴。首先有一个请求来了,wrapper会调用它,这个时候初始化一个它的实例。这个时候stage=0,subscript=0,然后加载所有的valve。依次调用它们。最后basic valve。但是哦,我们看到前面两个valve的invoke方法,都是先valveContext.invokeNext(request, response); 所以其实是basic里的invoke方法最先被执行,然后是valve2,最后是valve1.
下面看下两个valve类
pipeline--包含了改容器要唤醒的所有任务。每一个valve表示了一个特定的任务。容器的pipeline还有一个basic valve。valve可以自由添加一个或者多个。
类似于servlet过滤器,一个pipeline就像一个过滤链,每一个valve像一个过滤器。跟过滤器一样,一个valve可以操作传递给它的request和response方法。让一个阀门完成了处理,则进一步处理流水线中的下一个阀门,基本阀门总是在最后才被调用,但是会最先执行里面的方法。 一个容器可以实现pipeline接口。当容器的invoke方法被调用的时候,容器将会处理流水线中的阀门,并一个接一个的处理,直到所有的阀门都被处理完毕。
这个例子我们只有一个容器wrapper, servlet的封装类。它有一个servletClass属性来记录实际的servlet的名称。
首先,这个是启动类:
public final class Bootstrap5 { public static void main(String[] args) { HttpConnector connector = new HttpConnector(); Wrapper wrapper = new SimpleWrapper(); wrapper.setServletClass("com.m7.webserver.test2.PrimitiveServlet"); Loader loader = new SimpleLoader(); Valve valve1 = new HeaderLoggerValve(); Valve valve2 = new ClientIPLoggerValve(); wrapper.setLoader(loader); ((Pipeline) wrapper).addValve(valve1); ((Pipeline) wrapper).addValve(valve2); connector.setContainer(wrapper); try { connector.initialize(); connector.start(); // make the application wait until we press a key. System.in.read(); } catch (Exception e) { e.printStackTrace(); } }}
HeaderLoggerValve和ClientIPLoggerValve是两个阀门,用来打印请求头和用户ip.
然后我们来看这个SimpleWrapper.
public class SimpleWrapper implements Wrapper, Pipeline {// the servlet instanceprivate Servlet instance = null;private String servletClass;private Loader loader;private String name;private SimplePipeline pipeline = new SimplePipeline(this);protected Container parent = null;public SimpleWrapper() {pipeline.setBasic(new SimpleWrapperValve());}@Overridepublic synchronized void addValve(Valve valve) {pipeline.addValve(valve);}@Overridepublic Servlet allocate() throws ServletException {// Load and initialize our instance if necessaryif (instance == null) {try {instance = loadServlet();} catch (ServletException e) {throw e;} catch (Throwable e) {throw new ServletException("Cannot allocate a servlet instance", e);}}return instance;}private Servlet loadServlet() throws ServletException {if (instance != null)return instance;Servlet servlet = null;String actualClass = servletClass;if (actualClass == null) {throw new ServletException("servlet class has not been specified");}Loader loader = getLoader();// Acquire an instance of the class loader to be usedif (loader == null) {throw new ServletException("No loader.");}ClassLoader classLoader = loader.getClassLoader();// Load the specified servlet class from the appropriate class loaderClass classClass = null;try {if (classLoader != null) {classClass = classLoader.loadClass(actualClass);}} catch (ClassNotFoundException e) {throw new ServletException("Servlet class not found");}// Instantiate and initialize an instance of the servlet class itselftry {servlet = (Servlet) classClass.newInstance();} catch (Throwable e) {throw new ServletException("Failed to instantiate servlet");}// Call the initialization method of this servlettry {servlet.init(null);} catch (Throwable f) {throw new ServletException("Failed initialize servlet.");}return servlet;}@Overridepublic void invoke(Request request, Response response) throws IOException,ServletException {pipeline.invoke(request, response);}...}
这个是谁呢,这个就是下面要说的SimplePipeline的basic valve,它是用来调用真实servlet的service方法的
public class SimpleWrapperValve implements Valve, Contained {protected Container container;@Overridepublic void invoke(Request request, Response response,ValveContext valveContext) throws IOException, ServletException {SimpleWrapper wrapper = (SimpleWrapper) getContainer();ServletRequest sreq = request.getRequest();ServletResponse sres = response.getResponse();Servlet servlet = null;HttpServletRequest hreq = null;if (sreq instanceof HttpServletRequest)hreq = (HttpServletRequest) sreq;HttpServletResponse hres = null;if (sres instanceof HttpServletResponse)hres = (HttpServletResponse) sres;// Allocate a servlet instance to process this requesttry {servlet = wrapper.allocate();if (hres != null && hreq != null) {servlet.service(hreq, hres);} else {servlet.service(sreq, sres);}} catch (ServletException e) {}}@Overridepublic String getInfo() {return null;}@Overridepublic Container getContainer() {return container;}@Overridepublic void setContainer(Container container) {this.container = container;}}
SimpleWrapper里面有一个SimplePipeline,调simpleWrapper的invoke的话,就会调用它的invoke方法。SimplePipeline是这样的。
public class SimplePipeline implements Pipeline {public SimplePipeline(Container container) {setContainer(container);}// The basic Valve (if any) associated with this Pipeline.protected Valve basic = null;// The Container with which this Pipeline is associated.protected Container container = null;// the array of Valvesprotected Valve valves[] = new Valve[0];public void setContainer(Container container) {this.container = container;}@Overridepublic Valve getBasic() {return basic;}@Overridepublic void setBasic(Valve valve) {this.basic = valve;((Contained) valve).setContainer(container);}@Overridepublic void addValve(Valve valve) {if (valve instanceof Contained)((Contained) valve).setContainer(this.container);synchronized (valves) {Valve results[] = new Valve[valves.length + 1];System.arraycopy(valves, 0, results, 0, valves.length);results[valves.length] = valve;valves = results;}}@Overridepublic Valve[] getValves() {return valves;}@Overridepublic void invoke(Request request, Response response) throws IOException,ServletException {// Invoke the first Valve in this pipeline for this request(new SimplePipelineValveContext()).invokeNext(request, response);}@Overridepublic void removeValve(Valve valve) {}// this class is copied from org.apache.catalina.core.StandardPipeline// class's// StandardPipelineValveContext inner class.protected class SimplePipelineValveContext implements ValveContext {protected int stage = 0;@Overridepublic String getInfo() {return null;}@Overridepublic void invokeNext(Request request, Response response)throws IOException, ServletException {int subscript = stage;stage = stage + 1;// Invoke the requested Valve for the current request threadif (subscript < valves.length) {valves[subscript].invoke(request, response, this);} else if ((subscript == valves.length) && (basic != null)) {basic.invoke(request, response, this);} else {throw new ServletException("No valve");}}} // end of inner class}
这个类里面有一个内部类SimplePipelineValveContext。它继承了ValveContext,里面很重要的一个方法是invokeNext.它是这样工作滴。首先有一个请求来了,wrapper会调用它,这个时候初始化一个它的实例。这个时候stage=0,subscript=0,然后加载所有的valve。依次调用它们。最后basic valve。但是哦,我们看到前面两个valve的invoke方法,都是先valveContext.invokeNext(request, response); 所以其实是basic里的invoke方法最先被执行,然后是valve2,最后是valve1.
下面看下两个valve类
public class HeaderLoggerValve implements Valve, Contained {protected Container container;@Overridepublic void invoke(Request request, Response response,ValveContext valveContext) throws IOException, ServletException {// Pass this request on to the next valve in our pipelinevalveContext.invokeNext(request, response);System.out.println("Header Logger Valve");ServletRequest sreq = request.getRequest();if (sreq instanceof HttpServletRequest) {HttpServletRequest hreq = (HttpServletRequest) sreq;Enumeration headerNames = hreq.getHeaderNames();while (headerNames.hasMoreElements()) {String headerName = headerNames.nextElement().toString();String headerValue = hreq.getHeader(headerName);System.out.println(headerName + ":" + headerValue);}} elseSystem.out.println("Not an HTTP Request");System.out.println("------------------------------------");}@Overridepublic String getInfo() {return null;}@Overridepublic Container getContainer() {return container;}@Overridepublic void setContainer(Container container) {this.container = container;}}
public class ClientIPLoggerValve implements Valve, Contained { protected Container container; @Overridepublic void invoke(Request request, Response response, ValveContext valveContext) throws IOException, ServletException { // Pass this request on to the next valve in our pipeline valveContext.invokeNext(request, response); System.out.println("Client IP Logger Valve"); ServletRequest sreq = request.getRequest(); System.out.println(sreq.getRemoteAddr()); System.out.println("------------------------------------"); } @Overridepublic String getInfo() { return null; } @Overridepublic Container getContainer() { return container; } @Overridepublic void setContainer(Container container) { this.container = container; }}
这样就实现了pipeline的机制了。
代码参考:
how tomcat works
0 0
- 关于Tomcat的Pipeline机制
- tomcat:pipeline与valve机制
- Tomcat的管道(Pipeline)机制以及Context,Wrapper容器
- 关于详细的pipeline
- Tomcat容器结构及Pipeline机制
- Tomcat处理Http请求和Pipeline机制
- pipeline机制
- gstreamer中pipeline的工作机制
- redis的pipeline机制解析与注意事项
- HDFS Ozone的Pipeline实现机制
- 关于pipeline
- Tomcat 管道 Pipeline
- sklearn 中的 Pipeline 机制
- sklearn 中的 Pipeline 机制
- sklearn 中的 Pipeline 机制
- sklearn中的Pipeline机制
- Spark之pipeline机制
- Tomcat源码阅读之Container与Pipeline的设计
- 低功耗蓝牙包括的术语及概念
- Android开发中一些被冷落但却很有用的类和方法
- -webkit-background-size的使用
- how to download the souce code for trdp?
- Eclipse颜色主题插件:Eclipse Color Theme
- 关于Tomcat的Pipeline机制
- 通过Junit和Spring-Test测试SpringMVC的web应用
- Maven学习 (五) Elipse中发布一个Maven项目到Tomcat
- KM(N^3)模板(HDU2255)
- android中画虚线--.PathEffect类简单认识
- 安全测试学习笔记二(对于top 10 漏洞的分析)
- poj 2236 Wireless Network
- ARC 类型转换:显示转换 id 和 void *
- 根据CI模式弄的一个python访问数据的class