PipeLine and Value

参考博文 : http://gearever.iteye.com/blog/1540028

pipleLine 是管道,而value可以理解成是阀门 , 容器与容器间通过管道连接

所以容器中有管道这个组件(定义在ContainerBase中),管道中又存在阀门,来控制信息的流动。

一个管道中可以有多个阀门,以链表的形式表示!!Tomcat 启动时候,这些组件就会相应的启动!

如果把Tomcat比作一台大的机器的话,那么Container ,pipeline ,value就是他内部的一些小零件,当机器启动的时候,

那么相应着的,必须使小零件转动。

    StanardPipeline

    Value (interface) ---- ValueBase  --- (StanardEngineValue , StandardHostValue ..........) ;

    Value 的各种子类,不同之处在于invoke()定义的业务逻辑的不同!也就是说,你这个阀门究竟要做什么事,由他来定义!

 // coyoteAdapter service 方法: 这里是接着Tomcat接收请求那篇过来 ;

 public void service(org.apache.coyote.Request req,
    	                org.apache.coyote.Response res)
        throws Exception {
// 因为Connector中有一个成员变量container 并不是他所在的容器,而是请求传递的地方,然后调用管道中第一个value(StandardEngineValue) ;
	connector.getContainer().getPipeline().getFirst().invoke(request, response);
	//省略若干代码
    }

 // StandardEngineValue

public final void invoke(Request request, Response response)
        throws IOException, ServletException {

        // Select the Host to be used for this Request
        Host host = request.getHost();
        if (host == null) {
            response.sendError
                (HttpServletResponse.SC_BAD_REQUEST,
                 sm.getString("standardEngine.noHost", 
                              request.getServerName()));
            return;
        }

        // Ask this Host to process this request
        host.getPipeline().getFirst().invoke(request, response); 
    }

 StandardHost中ErrorReportValue :

  

public void invoke(Request request, Response response)
        throws IOException, ServletException {
        // Perform the request 调用StandardHost的pipeLine 中下一个value
        getNext().invoke(request, response);
        //省略若干代码        
    }
context.getPipeline().getFirst().invoke(request, response);
  
wrapper.getPipeline().getFirst().invoke(request, response);

可以定制化Value , 通常在server.xml中配置,只要继承了org.apache.catalina.valves.ValveBase 

<Engine name="Catalina" defaultHost="localhost">  
  <Valve className="MyValve0"/>  
  <Valve className="MyValve1"/>  
  <Valve className="MyValve2"/>  
   ……  
  <Host name="localhost"  appBase="webapps">  
  </Host>  
</Engine>  

 当定制了Value时,就会调用pipeLine 中add方法,把Value添加到相应的管道中!

  就像我们在上面看到的一样,每个容器都要一个缺省的(就是不要在server.xml)中配置的Value;

  他们总是位于value链的末端!最后才被调用!就像上面看到的一样,我们调用的都是第一个,并没有看到它调用了整个value链啊。

  原因就在这,因为这些每个容器默认的value 永远都是在最后一个,所以不存在会调用下一个的情况(getNext()),但是,像自己定义的

  的Value , 那么你在实现invoke()的时候,内部就必须getNext(),即调用下一个Value的操作,就像上面的ErrorReportValue一样!

 

  看下面的addvalue() :

 public void addValve(Valve valve) {
    
        // Validate that we can add this Valve
        if (valve instanceof Contained)
            ((Contained) valve).setContainer(this.container);

        // Start the new component if necessary
        if (started) {
            if (valve instanceof Lifecycle) {
                try {
                    ((Lifecycle) valve).start();
                } catch (LifecycleException e) {
                    log.error("StandardPipeline.addValve: start: ", e);
                }
            }
            // Register the newly added valve
            registerValve(valve);
        }

        // Add this Valve to the set associated with this Pipeline
        if (first == null) {
        	first = valve;
        	valve.setNext(basic); // basic 就是缺省的 添加到最后 
        } else {
            Valve current = first;
            while (current != null) { //这里在一个链表中找到basic , 然后在它前面插入
				if (current.getNext() == basic) { 
					current.setNext(valve);
					valve.setNext(basic);
					break;
				}
				current = current.getNext();
			}
        }

    }

 四大容器的标准valve的调用逻辑图:

  

 

猜你喜欢

转载自kainever7.iteye.com/blog/2206914
今日推荐