2013-11-11java
ApplicationFilterFactory和ApplicationFilterChain都是跟Filter相關的類,前者根據註冊在Wrapper的Filter,通過篩選成產後者,後者是多個Filter集合的管理類。設計模式
ApplicationFilterFactory
是個單例工廠類,負責爲Servlet生成FilterChain,在createFilterChain(ServletRequest, Wrapper, Servlet)方法內部,經過URL與Filter URL過濾規則配置爲Servlet生成FilterChain,具體以下:tomcat
/** * Construct and return a FilterChain implementation that will wrap the * execution of the specified servlet instance. If we should not execute a * filter chain at all, return <code>null</code>. * * @param request * The servlet request we are processing * @param servlet * The servlet instance to be wrapped */ public ApplicationFilterChain createFilterChain(ServletRequest request, Wrapper wrapper, Servlet servlet) { // get the dispatcher type int dispatcher = -1; if (request.getAttribute(DISPATCHER_TYPE_ATTR) != null) { Integer dispatcherInt = (Integer) request .getAttribute(DISPATCHER_TYPE_ATTR); dispatcher = dispatcherInt.intValue(); } String requestPath = null; Object attribute = request.getAttribute(DISPATCHER_REQUEST_PATH_ATTR); if (attribute != null) { requestPath = attribute.toString(); } HttpServletRequest hreq = null; if (request instanceof HttpServletRequest) hreq = (HttpServletRequest) request; // If there is no servlet to execute, return null if (servlet == null) return (null); boolean comet = false; // Create and initialize a filter chain object ApplicationFilterChain filterChain = null; if (request instanceof Request) { Request req = (Request) request; comet = req.isComet(); if (Globals.IS_SECURITY_ENABLED) { // Security: Do not recycle filterChain = new ApplicationFilterChain(); if (comet) { req.setFilterChain(filterChain); } } else { filterChain = (ApplicationFilterChain) req.getFilterChain(); if (filterChain == null) { filterChain = new ApplicationFilterChain(); req.setFilterChain(filterChain); } } } else { // Request dispatcher in use filterChain = new ApplicationFilterChain(); } filterChain.setServlet(servlet); filterChain .setSupport(((StandardWrapper) wrapper).getInstanceSupport()); // 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); // Acquire the information we will need to match filter mappings String servletName = wrapper.getName(); // 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; } boolean isCometFilter = false; if (comet) { try { isCometFilter = filterConfig.getFilter() instanceof CometFilter; } catch (Exception e) { // Note: The try catch is there because getFilter has a lot // of // declared exceptions. However, the filter is allocated // much // earlier } if (isCometFilter) { filterChain.addFilter(filterConfig); } } else { 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; } if (!matchFiltersServlet(filterMaps[i], servletName)) continue; ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) context .findFilterConfig(filterMaps[i].getFilterName()); if (filterConfig == null) { ; // FIXME - log configuration problem continue; } boolean isCometFilter = false; if (comet) { try { isCometFilter = filterConfig.getFilter() instanceof CometFilter; } catch (Exception e) { // Note: The try catch is there because getFilter has a lot // of // declared exceptions. However, the filter is allocated // much // earlier } if (isCometFilter) { filterChain.addFilter(filterConfig); } } else { filterChain.addFilter(filterConfig); } } // Return the completed filter chain return (filterChain); }
以上ApplicationFilterFactory完成了生產ApplicationFilterChain的任務,爲Wrapper(Servlet)從Context上面篩選Filter並添加到FilterChian中。在ApplicationFilterChain中,主要是doFilter(ServletRequest, ServletResponse)方法完成Filter過濾Serlvet且最後調用servlet的service()方法的功能。安全
ApplicationFilterChain 在ApplicationFilterFactory完成生產FilterChain的任務後,ApplicationFIlterChain的功能則是使用FilterChain來過濾Servlet,因爲它實現了Filterchain接口,因此具備Filterchain的功能,而且最終調用servlet.service()方法,在doFilter(ServletRequest, ServletResponse)方法中調用internalDoFilter(ServletRequest, ServletResponse)來完成,首先使用Filter過濾Servlet,最後完成service方法的調用。具體以下:app
/** * 調用doFilter方法遞歸過濾servlet,在遞歸最內部調用servlet.service() * @param request * @param response * @throws IOException * @throws ServletException */ private void internalDoFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { // Call the next filter if there is one //判斷是否已經執行到FilterChain鏈尾部 if (pos < n) { //取當前過濾Filter配置信息 ApplicationFilterConfig filterConfig = filters[pos++]; Filter filter = null; try { //取Filter filter = filterConfig.getFilter(); //事件通知 support.fireInstanceEvent(InstanceEvent.BEFORE_FILTER_EVENT, filter, request, response); //安全判斷 if (Globals.IS_SECURITY_ENABLED) { final ServletRequest req = request; final ServletResponse res = response; Principal principal = ((HttpServletRequest) req) .getUserPrincipal(); Object[] args = new Object[] { req, res, this }; //執行調用Filter的doFilter()方法 SecurityUtil.doAsPrivilege("doFilter", filter, classType, args, principal); args = null; } else { //執行調用Filter的doFilter()方法 filter.doFilter(request, response, this); } //完成Filter過濾事件通知 support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request, response); } catch (IOException e) { if (filter != null) support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request, response, e); throw e; } catch (ServletException e) { if (filter != null) support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request, response, e); throw e; } catch (RuntimeException e) { if (filter != null) support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request, response, e); throw e; } catch (Throwable e) { if (filter != null) support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request, response, e); throw new ServletException(sm.getString("filterChain.filter"), e); } return; } // We fell off the end of the chain -- call the servlet instance try { //安全校驗 if (Globals.STRICT_SERVLET_COMPLIANCE) { lastServicedRequest.set(request); lastServicedResponse.set(response); } //調用servlet.service()事件通知 support.fireInstanceEvent(InstanceEvent.BEFORE_SERVICE_EVENT, servlet, request, response); if ((request instanceof HttpServletRequest) && (response instanceof HttpServletResponse)) { //安全校驗 if (Globals.IS_SECURITY_ENABLED) { final ServletRequest req = request; final ServletResponse res = response; Principal principal = ((HttpServletRequest) req) .getUserPrincipal(); Object[] args = new Object[] { req, res }; SecurityUtil.doAsPrivilege("service", servlet, classTypeUsedInService, args, principal); args = null; } else { //調用servlet.service()方法 servlet.service((HttpServletRequest) request, (HttpServletResponse) response); } } else { //調用servlet.service()方法 servlet.service(request, response); } //完成servlet.service()調用事件通知 support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response); } catch (IOException e) { support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response, e); throw e; } catch (ServletException e) { support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response, e); throw e; } catch (RuntimeException e) { support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response, e); throw e; } catch (Throwable e) { support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response, e); throw new ServletException(sm.getString("filterChain.servlet"), e); } finally { //安全校驗 if (Globals.STRICT_SERVLET_COMPLIANCE) { lastServicedRequest.set(null); lastServicedResponse.set(null); } } }
在internalDoFilter(ServletRequest, ServletResponse)方法中,能夠看到servlet是在因此FilterChain最一個Filter前置過濾完成後調用,調用完成後依次遞歸出來,逆序調用FilterChain上的Filter後置過濾servlet。在Filter中能夠添加校驗邏輯,日誌記錄等信息。到目前爲止,tomcat已經完成了使用servlet處理請求信息的功能。ui
FilterChain的模式是設計模式中的責任鏈模式,該模式的必需要通過全部的鏈上過濾完後纔會執行最後的操做。this
還堅持url