Tomcat启动时会创建一个线程池和连接器,开启端口监听网络请求,然后解析网络请求并且封装到Request、Response类中,由CoyoteAdapter的service(org.apache.coyote.Request req, org.apache.coyote.Response res)
方法开始交由Container容器处理,最后将容器处理完的响应数据交由连接器发送给请求调用方。
connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);V
这里有一个概念:每一个容器Container都有一个pipeline负责对应若干Valve的维护,Valve就是负责相应容器的逻辑处理器。每一个容器组件都有个默认的Valve,被设置为Basic,比如StandardEngineValve、StandardHostValve、StandardContextValve、StandardWrapperValve,用于该组件最后调用下级组件。在相应组件的构造函数内创建:
/**
* Create a new StandardEngine component with the default basic Valve.
*/
public StandardEngine() {
super();
//在这里设置了,其余几个组件也一样
pipeline.setBasic(new StandardEngineValve());
/* Set the jmvRoute using the system property jvmRoute */
try {
setJvmRoute(System.getProperty("jvmRoute"));
} catch(Exception ex) {
log.warn(sm.getString("standardEngine.jvmRouteFail"));
}
// By default, the engine will hold the reloading thread
backgroundProcessorDelay = 10;
}
在Pipeline里有两个概念,一个是Basic,指定最基本的处理器,其最终都会执行getPipeline().getFirst().invoke(request, response)
调用下级容器的Valve;另一个是First,默认情况下是空的,但是可以通过addValve(Valve valve)
方法添加,代码如下:
public void addValve(Valve valve) {
......
// Add this Valve to the set associated with this Pipeline
if (first == null) {
first = valve;
valve.setNext(basic);
} else {
Valve current = first;
while (current != null) {
if (current.getNext() == basic) {
current.setNext(valve);
valve.setNext(basic);
break;
}
current = current.getNext();
}
}
container.fireContainerEvent(Container.ADD_VALVE_EVENT, valve);
}
可以看到每一个调用addValve添加的Valve都会加入到Valve的单向链表中,最后一个Basic Valve之前。
附上一个各个Pipeline的流程图:
125 if (!asyncAtStart && !context.fireRequestInitEvent(request.getRequest())) 创建请求HttpServletRequest,并执行ServletRequestListener监听器的requestInitialized(ServletRequestEvent sre)方法
#StandardContext
//创建RequestFacade implements HttpServletRequest,(interface HttpServletRequest extends ServletRequest)
public HttpServletRequest getRequest() {
if (facade == null) {
facade = new RequestFacade(this);
}
if (applicationRequest == null) {
applicationRequest = facade;
}
return applicationRequest;
}
139 context.getPipeline().getFirst().invoke(request, response); 执行AuthenticatorBase的认证方法,最终执行StandardContextValve的invoke方法
//执行StandardContext中注册了ServletRequestListener监听器的requestDestroyed销毁请求的方法。
181 context.fireRequestDestroyEvent(request.getRequest());
135 servlet = wrapper.allocate(); 如果servlet没有初始化,就执行初始化
在Tomcat的启动阶段就会将那些loadOnStartup值大于等于0的Servlet初始化,然而如果为负数的那些Servlet就会在对应生效的请求中执行初始化。
#StandardWrapper
//this:StandardWrapper
StandardWrapperFacade facade = new StandardWrapperFacade(this);
servlet.init(facade);
或者是通过 #StandardWrapper 761 instance = loadServlet(); 创建Servlet对象,处理@MultipartConfig注解并初始化Servlet。
// 173 为请求创建FilterChain
ApplicationFilterChain filterChain = ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
#ApplicationFilterFactory
public static ApplicationFilterChain createFilterChain(ServletRequest request,
Wrapper wrapper, Servlet servlet) {
// If there is no servlet to execute, return null
if (servlet == null)
return null;
// 创建过滤器链FilterChain
ApplicationFilterChain filterChain = null;
if (request instanceof Request) {
Request req = (Request) request;
if (Globals.IS_SECURITY_ENABLED) {
// Security: Do not recycle
filterChain = new ApplicationFilterChain();
} else {
filterChain = (ApplicationFilterChain) req.getFilterChain();
if (filterChain == null) {
filterChain = new ApplicationFilterChain();
req.setFilterChain(filterChain);
}
}
} else {
// Request dispatcher in use
filterChain = new ApplicationFilterChain();
}
//为过滤器设置Servlet处理器
filterChain.setServlet(servlet);
filterChain.setServletSupportsAsync(wrapper.isAsyncSupported());
// 从StandardContext中获取filter集合
StandardContext context = (StandardContext) wrapper.getParent();
FilterMap filterMaps[] = context.findFilterMaps();
// 如果没有找到filter注册那么FilterChain中就不需要设置Filter了,直接返回。
if ((filterMaps == null) || (filterMaps.length == 0))
return filterChain;
// Acquire the information we will need to match filter mappings
DispatcherType dispatcher =
(DispatcherType) request.getAttribute(Globals.DISPATCHER_TYPE_ATTR);
String requestPath = null;
Object attribute = request.getAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR);
if (attribute != null){
requestPath = attribute.toString();
}
String servletName = wrapper.getName();
// Add the relevant path-mapped filters to this filter chain
for (int i = 0; i < filterMaps.length; i++) {
//匹配请求的调度方式FORWARD、INCLUDE、REQUEST、ERROR、ASYNC,默认情况下是REQUEST
if (!matchDispatcher(filterMaps[i] ,dispatcher)) {
continue;
}
//匹配url是否拦截
if (!matchFiltersURL(filterMaps[i], requestPath))
continue;
//从StandardContext中获取该Filter
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
context.findFilterConfig(filterMaps[i].getFilterName());
if (filterConfig == null) {
// FIXME - log configuration problem
continue;
}
//将该Filter加入过滤器链
filterChain.addFilter(filterConfig);
}
// Add filters that match on servlet name second
for (int i = 0; i < filterMaps.length; i++) {
if (!matchDispatcher(filterMaps[i] ,dispatcher)) {
continue;
}
//根据Filter配置的Servlet过滤
if (!matchFiltersServlet(filterMaps[i], servletName))
continue;
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
context.findFilterConfig(filterMaps[i].getFilterName());
if (filterConfig == null) {
// FIXME - log configuration problem
continue;
}
//加入过滤器链
filterChain.addFilter(filterConfig);
}
// Return the completed filter chain
return filterChain;
}
匹配请求的调度方式FORWARD、INCLUDE、REQUEST、ERROR、ASYNC,默认情况下是REQUEST:
匹配url是否拦截:
具体的匹配规则,代码如下:
private static boolean matchFiltersURL(String testPath, String requestPath) {
if (testPath == null)
return false;
// Case 1 - Exact Match
if (testPath.equals(requestPath))
return true;
// Case 2 - Path Match ("/.../*")
if (testPath.equals("/*"))
return true;
if (testPath.endsWith("/*")) {
if (testPath.regionMatches(0, requestPath, 0,
testPath.length() - 2)) {
if (requestPath.length() == (testPath.length() - 2)) {
return true;
} else if ('/' == requestPath.charAt(testPath.length() - 2)) {
return true;
}
}
return false;
}
// Case 3 - Extension Match
if (testPath.startsWith("*.")) {
int slash = requestPath.lastIndexOf('/');
int period = requestPath.lastIndexOf('.');
if ((slash >= 0) && (period > slash)
&& (period != requestPath.length() - 1)
&& ((requestPath.length() - period)
== (testPath.length() - 1))) {
return testPath.regionMatches(2, requestPath, period + 1,
testPath.length() - 2);
}
}
// Case 4 - "Default" Match
return false; // NOTE - Not relevant for selecting filters
}
根据Filter配置的Servlet过滤:
总的来说,请求的调度优先级最高必须满足,其次先匹配URL,如果满足就直接加入FilterChain,其次在匹配ServletName,URL和Servlet都可以设置是否全部满足和单个满足。如果一个Filter这两者都满足,最后在过滤器链的添加中会先判断加入的Filter是否存在,不会重复添加。
201 filterChain.doFilter(request.getRequest(), response.getResponse()); 执行doFilter方法进行过滤器链的工作
#ApplicationFilterChain
@Override
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
......
internalDoFilter(request,response);
}
}
最后调用ApplicationFilterChain # internalDoFilter(ServletRequest request,ServletResponse response)方法(主要逻辑如下):
private void internalDoFilter(ServletRequest request,
ServletResponse response)
throws IOException, ServletException {
//n表示此过滤器链中的filter个数;
//pos表示当前执行到的过滤器的下标,从0开始
if (pos < n) {
ApplicationFilterConfig filterConfig = filters[pos++];
try {
Filter filter = filterConfig.getFilter();
......
filter.doFilter(request, response, this);
} catch (){
......
}
return;
}
//当此过滤器链中所有的过滤器都执行完了,则调用下面的Servlet处理器
......
servlet.service(request, response);
......
可以看到过滤器链是通过类似递归的责任链模式过滤请求和响应的。当然我们自定义的Filter中必须执行FilterChain#doFilter(ServletRequest servletRequest, ServletResponse servletResponse)
方法。例如:
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("doFilter");
filterChain.doFilter(servletRequest, servletResponse);
}
请求属性监听ServletRequestAttributeListener的调用逻辑都在org.apache.catalina.connector.Request
类中,和ServletContext,ServletRequest的监听类似。
261 filterChain.release();
267 wrapper.deallocate(servlet);