当前位置: 首页 > 工具软件 > Valve Proton > 使用案例 >

tomcat:pipeline与valve机制

西门凯康
2023-12-01

协作模式

每个容器包含一个pipeline,每个pipeline包含一个valve集合,位于前面的的valve做完业务处理后将调用后面的valve做业务处理,而容器的缺省valve位于集合的最后一个位置,负责调用下层容器的pipeline的第一个valve做业务处理,调用会从Engine的第一个valve调用开始,一直执行到调用Wrapper的缺省valve:StandardWrapperValve,而filter与servlet的处理就是在这个valve中进行的 。Engine的第一个valve是由Adapter调用的,在connector章节中也看到CoyoteAdapter在处理完request以后会执行connector.getContainer().getPipeline().getFirst().invoke(request, response);

这其中讲了几个点说一下

  1. 每个容器都有一个pipeline
  2. 每个容器都有个缺省的valve
  3. 每个容器缺省的valve都将在最后一个被调用

源码窥探

Engine缺省的valve StandardEngineValve

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

    // 定位host  
    Host host = request.getHost();  
    if (host == null) {  
        ......  
        return;  
    }  

    // 调用host的第一个valve  
    host.getPipeline().getFirst().invoke(request, response);  

} 

Host的缺省valve StandardHostValve

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

    // 定位context  
    Context context = request.getContext();  
    if (context == null) {  
        ......  
        return;  
    }  

    ......  

    // 调用context的第一个valve  
    context.getPipeline().getFirst().invoke(request, response); 
    ...
}

context的缺省valve StandardContextValve:

public final void invoke(Request request, Response response)  
    throws IOException, ServletException {  
    ......  
    // 定位wrapper  
    Wrapper wrapper = request.getWrapper();  
    if (wrapper == null) {  
        notFound(response);  
        return;  
    } else if (wrapper.isUnavailable()) {  
        ......  
    }  
    // Normal request processing  
    //web.xml中配置web-app/listener/listener-class  
    Object instances[] = context.getApplicationEventListeners();  

    ServletRequestEvent event = null;  

    //响应request初始化事件,具体的响应listener是可配置的   
    ......  
    //调用wrapper的第一个valve  
    wrapper.getPipeline().getFirst().invoke(request, response);   
    ......               
}  

Wrapper的缺省valve

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

    ......  
    requestCount++;  
    //定位wrapper  
    StandardWrapper wrapper = (StandardWrapper) getContainer();  
    Servlet servlet = null;  
    Context context = (Context) wrapper.getParent();  
    ......  
    // Allocate a servlet instance to process this request  
    try {  
        if (!unavailable) {  
            //加载servlet  
            servlet = wrapper.allocate();                  
        }  
    } catch (UnavailableException e) {  
        ......  
    }   
    ......  
    // 根据配置建立一个filter-servlet的处理链表,servlet在链表的尾端  
    ApplicationFilterFactory factory =  
        ApplicationFilterFactory.getInstance();  
    ApplicationFilterChain filterChain =  
        factory.createFilterChain(request, wrapper, servlet);  
    // Reset comet flag value after creating the filter chain  
    request.setComet(false);  
    ......
} 

定制valve:

public void invoke(Request request, Response response)   
                throws IOException, ServletException {   
    Log log = container.getLogger();  
    // Log pre-service information   
    log.info("REQUEST URI =" + request.getRequestURI());   
    ......   
    log.info(" queryString=" + request.getQueryString());   
    ......   
    log.info("-------------------------------------------------------");   
    // 调用下一个valve  
    getNext().invoke(request, response);   
    // Log post-service information   
    log.info("-------------------------------------------------------");   
    ......   
    log.info(" contentType=" + response.getContentType());   
    Cookie rcookies[] = response.getCookies();   
    for (int i = 0; i < rcookies.length; i++) {   
        log.info(" cookie=" + rcookies[i].getName() + "=" +   
            rcookies[i].getValue() + "; domain=" +   
            rcookies[i].getDomain() + "; path=" + rcookies[i].getPath());   
    }   
    String rhnames[] = response.getHeaderNames();   
    for (int i = 0; i < rhnames.length; i++) {   
        String rhvalues[] = response.getHeaderValues(rhnames[i]);   
        for (int j = 0; j < rhvalues.length; j++)   
        log.info(" header=" + rhnames[i] + "=" + rhvalues[j]);            
    }  
    log.info(" message=" + response.getMessage());   
    log.info("========================================================");   
}  

注意getNext().invoke(request, response);因为自定义的valve与容器缺省的valve不同,它需要调用它的下一个vlave而不是下层容器的pipeline的第一个valve,例如:wrapper.getPipeline().getFirst().invoke(request, response);

 类似资料: