您的位置:首页 > 运维架构 > Tomcat

tomcat:pipeline与valve机制

2016-11-30 18:30 567 查看

协作模式

每个容器包含一个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);


这其中讲了几个点说一下

每个容器都有一个pipeline

每个容器都有个缺省的valve

每个容器缺省的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);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  tomcat