Filter责任链模式
Filter责任链的创建
org.apache.catalina.core.ApplicationFilterFactory#createFilterChain, 此方法是被org.apache.catalina.core.StandardWrapperValve#invoke调用的, 对每个request都会创建FilterChain
public static ApplicationFilterChain createFilterChain(ServletRequest request, Wrapper wrapper, Servlet servlet) { //传入参数必须有一个servlet,这个servlet是在链的末尾被调用的. 这个servlet的查找过程是根据request的URI从web.xml配置中匹配出来的 // If there is no servlet to execute, return null if (servlet == null) return null; // Create and initialize a filter chain object ApplicationFilterChain filterChain = null; if (request instanceof Request) { //..... } else { // Request dispatcher in use filterChain = new ApplicationFilterChain(); } // 责任链上绑定一个servlet filterChain.setServlet(servlet); filterChain.setServletSupportsAsync(wrapper.isAsyncSupported()); // Acquire the filter mappings for this Context StandardContext context = (StandardContext) wrapper.getParent(); FilterMap filterMaps[] = context.findFilterMaps(); // If there are no filter mappings, we are done if ((filterMaps == null) || (filterMaps.length == 0)) return (filterChain); // ... //根据web.xml中filter的配置查找是否和当前request匹配 // Add the relevant path-mapped filters to this filter chain for (int i = 0; i < filterMaps.length; i++) { if (!matchDispatcher(filterMaps[i] ,dispatcher)) { continue; } if (!matchFiltersURL(filterMaps[i], requestPath)) continue; ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) context.findFilterConfig(filterMaps[i].getFilterName()); if (filterConfig == null) { // FIXME - log configuration problem continue; }
// 和request URI匹配,则filter会加入到责任链中 filterChain.addFilter(filterConfig); } /.....// Return the completed filter chain return filterChain; }
filterChain创建完成后就会调用doFilter启用这个链, 此方法也是被org.apache.catalina.core.StandardWrapperValve#invoke调用的
org.apache.catalina.core.ApplicationFilterChain#doFilter
1 private void internalDoFilter(ServletRequest request, 2 ServletResponse response) 3 throws IOException, ServletException { 4 5 // Call the next filter if there is one 6 if (pos < n) { 7 //调用下一个filter, 每调用一次 当前pos都会++ 8 ApplicationFilterConfig filterConfig = filters[pos++]; 9 try { 10 Filter filter = filterConfig.getFilter(); 11 12 //... 13 filter.doFilter(request, response, this); 14 15 } catch (IOException | ServletException | RuntimeException e) { 16 throw e; 17 } catch (Throwable e) { 18 // ... 19 } 20 return; 21 } 22 23 // We fell off the end of the chain -- call the servlet instance 24 try { 25 if (request.isAsyncSupported() && !servletSupportsAsync) { 26 request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, 27 Boolean.FALSE); 28 } 29 // ... 在链的末尾,调用具体servlet的doService 30 servlet.service(request, response); 31 // 32 } catch (IOException | ServletException | RuntimeException e) { 33 throw e; 34 } catch (Throwable e) { 35 //... 36 } finally { 37 //... 38 } 39 }
@@@build beautiful things, share happiness@@@