How Tomcat Works(十四)补充

系统 1838 0

How Tomcat Works(十四) 中,本人并没有对javax.servlet.Filter及javax.servlet.FilterChain做详细的描述,本文在这里做一下补充

FilterChain接口只有一个方法,方法声明如下:

public void doFilter ( ServletRequest request, ServletResponse response ) throws IOException, ServletException;

在tomcat中,org.apache.catalina.core.ApplicationFilterChain类实现了该接口

ApplicationFilterChain类采用一个私有成员变量private ArrayList filters = new ArrayList()保存ApplicationFilterConfig对象的集合,ApplicationFilterConfig类实现了javax.servlet.FilterConfig接口,封装了对Filter实例的管理

下面是向ArrayList filters集合添加ApplicationFilterConfig实例

      
        void
      
      
         addFilter(ApplicationFilterConfig filterConfig) {

        
      
      
        this
      
      
        .filters.add(filterConfig);

    }
      
    

setServlet()方法用于向ApplicationFilterChain对象设置当前的servlet实例

      
        void
      
      
         setServlet(Servlet servlet) {

        
      
      
        this
      
      .servlet =
      
         servlet;

    }
      
    

在ApplicationFilterChain类的实现FilterChain接口方法doFilter()中,调用了其私有方法internalDoFilter(),下面是该方法的具体实现

      
        private
      
      
        void
      
      
         internalDoFilter(ServletRequest request, ServletResponse response)
        
      
      
        throws
      
      
         IOException, ServletException {

        
      
      
        //
      
      
         Construct an iterator the first time this method is called
      
      
        if
      
       (
      
        this
      
      .iterator == 
      
        null
      
      
        )
            
      
      
        this
      
      .iterator =
      
         filters.iterator();

        
      
      
        //
      
      
         Call the next filter if there is one
      
      
        if
      
       (
      
        this
      
      
        .iterator.hasNext()) {
            ApplicationFilterConfig filterConfig 
      
      =
      
        
              (ApplicationFilterConfig) iterator.next();
            Filter filter 
      
      = 
      
        null
      
      
        ;
            
      
      
        try
      
      
         {
                filter 
      
      =
      
         filterConfig.getFilter();
                support.fireInstanceEvent(InstanceEvent.BEFORE_FILTER_EVENT,
                                          filter, request, response);
                filter.doFilter(request, response, 
      
      
        this
      
      
        );
                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
      
      
         {
            support.fireInstanceEvent(InstanceEvent.BEFORE_SERVICE_EVENT,
                                      servlet, request, response);
            
      
      
        if
      
       ((request 
      
        instanceof
      
       HttpServletRequest) &&
      
        
                (response 
      
      
        instanceof
      
      
         HttpServletResponse)) {
                servlet.service((HttpServletRequest) request,
                                (HttpServletResponse) response);
            } 
      
      
        else
      
      
         {
                servlet.service(request, response);
            }
            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);
        }

    }
      
    

在调用了filter.doFilter(request, response, this)方法之后,继续执行servlet的service()方法

这里的this是ApplicationFilterChain对象自身,在我们编写的Filter实现类里面同在在执行完我们实现的过滤方法之后会继续调用FilterChain对象的void doFilter(ServletRequest request, ServletResponse response)方法,我们自定义的过滤器通常会这样实现:

      
        class
      
       SampleFilter 
      
        implements
      
      
         Filter {   
      ........   
      
      
      
        public
      
      
        void
      
      
         doFilter(ServletRequest request, ServletResponse response,FilterChain chain)   
        
      
      
        throws
      
      
         IOException, ServletException {   
            
         
      
      
        //
      
      
        do something    
      
      
                 .....   
         
      
      
        //
      
      
        request, response传递给下一个过滤器进行过滤   
      
      
                 chain.doFilter(request, response);   
    }   
         
}  
      
    

ApplicationFilterConfig类实现了javax.servlet.FilterConfig接口,代表一个Filter容器,FilterConfig接口定义如下:

      
        public
      
      
        interface
      
      
         FilterConfig {    
      
      
        public
      
      
         String getFilterName(); 
      
      
        public
      
      
         ServletContext getServletContext();    
      
      
        public
      
      
         String getInitParameter(String name);   
      
      
        public
      
      
         Enumeration getInitParameterNames();
}
      
    

可以通过传入org.apache.catalina.Context对象和FilterDef对象(FilterDef对象用于对过滤器类的定义,包括过滤器类名、相关参数等)传给其构造函数构造一个ApplicationFilterConfig对象:

      
        public
      
      
         ApplicationFilterConfig(Context context, FilterDef filterDef)
        
      
      
        throws
      
      
         ClassCastException, ClassNotFoundException,
               IllegalAccessException, InstantiationException,
               ServletException {

        
      
      
        super
      
      
        ();
        
      
      
        this
      
      .context =
      
         context;
        setFilterDef(filterDef);

    }
      
    

ApplicationFilterConfig类的getFilter()方法返回一个javax.servlet.Filter对象,该方法负责载入并实例化一个过滤器类

      Filter getFilter() 
      
        throws
      
      
         ClassCastException, ClassNotFoundException,
        IllegalAccessException, InstantiationException, ServletException {

        
      
      
        //
      
      
         Return the existing filter instance, if any
      
      
        if
      
       (
      
        this
      
      .filter != 
      
        null
      
      
        )
            
      
      
        return
      
       (
      
        this
      
      
        .filter);

        
      
      
        //
      
      
         Identify the class loader we will be using
      
      
        String filterClass =
      
         filterDef.getFilterClass();
        ClassLoader classLoader 
      
      = 
      
        null
      
      
        ;
        
      
      
        if
      
       (filterClass.startsWith("org.apache.catalina."
      
        ))
            classLoader 
      
      = 
      
        this
      
      
        .getClass().getClassLoader();
        
      
      
        else
      
      
        
            classLoader 
      
      =
      
         context.getLoader().getClassLoader();

        ClassLoader oldCtxClassLoader 
      
      =
      
        
            Thread.currentThread().getContextClassLoader();

        
      
      
        //
      
      
         Instantiate a new instance of this filter and return it
      
      
        Class clazz =
      
         classLoader.loadClass(filterClass);
        
      
      
        this
      
      .filter =
      
         (Filter) clazz.newInstance();
        filter.init(
      
      
        this
      
      
        );
        
      
      
        return
      
       (
      
        this
      
      
        .filter);

    }
      
    

现在,也许我们更容易理解StandardWrapperValve类中创建过滤器链createFilterChain()方法了

      
        private
      
      
         ApplicationFilterChain createFilterChain(Request request,
                                                     Servlet servlet) {

        
      
      
        //
      
      
         If there is no servlet to execute, return null
      
      
        if
      
       (servlet == 
      
        null
      
      
        )
            
      
      
        return
      
       (
      
        null
      
      
        );

        
      
      
        //
      
      
         Create and initialize a filter chain object
      
      
        ApplicationFilterChain filterChain =
          
      
        new
      
      
         ApplicationFilterChain();
        filterChain.setServlet(servlet);
        StandardWrapper wrapper 
      
      =
      
         (StandardWrapper) getContainer();
        filterChain.setSupport(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);

      
      
        //
      
      
                if (debug >= 1)

      
      
        //
      
      
                    log("createFilterChain:  Processing " + filterMaps.length +

      
      
        //
      
      
                        " filter map entries");

        
      
      
        //
      
      
         Acquire the information we will need to match filter mappings
      
      
        String requestPath = 
      
        null
      
      
        ;
        
      
      
        if
      
       (request 
      
        instanceof
      
      
         HttpRequest) {
            HttpServletRequest hreq 
      
      =
      
        
                (HttpServletRequest) request.getRequest();
            String contextPath 
      
      =
      
         hreq.getContextPath();
            
      
      
        if
      
       (contextPath == 
      
        null
      
      
        )
                contextPath 
      
      = ""
      
        ;
            String requestURI 
      
      =
      
         ((HttpRequest) request).getDecodedRequestURI();
            
      
      
        if
      
       (requestURI.length() >=
      
         contextPath.length())
                requestPath 
      
      =
      
         requestURI.substring(contextPath.length());
        }
        String servletName 
      
      =
      
         wrapper.getName();

      
      
        //
      
      
                if (debug >= 1) {

      
      
        //
      
      
                    log(" requestPath=" + requestPath);

      
      
        //
      
      
                    log(" servletName=" + servletName);

      
      
        //
      
      
                }
      
      
        int
      
       n = 0
      
        ;

        
      
      
        //
      
      
         Add the relevant path-mapped filters to this filter chain
      
      
        for
      
       (
      
        int
      
       i = 0; i < filterMaps.length; i++
      
        ) {

      
      
        //
      
      
                    if (debug >= 2)

      
      
        //
      
      
                        log(" Checking path-mapped filter '" +

      
      
        //
      
      
                            filterMaps[i] + "'");
      
      
        if
      
       (!
      
        matchFiltersURL(filterMaps[i], requestPath))
                
      
      
        continue
      
      
        ;
            ApplicationFilterConfig filterConfig 
      
      =
      
         (ApplicationFilterConfig)
                context.findFilterConfig(filterMaps[i].getFilterName());
            
      
      
        if
      
       (filterConfig == 
      
        null
      
      
        ) {

      
      
        //
      
      
                        if (debug >= 2)

      
      
        //
      
      
                            log(" Missing path-mapped filter '" +

      
      
        //
      
      
                                filterMaps[i] + "'");
      
      
                ;       
      
        //
      
      
         FIXME - log configuration problem
      
      
        continue
      
      
        ;
            }

      
      
        //
      
      
                    if (debug >= 2)

      
      
        //
      
      
                        log(" Adding path-mapped filter '" +

      
      
        //
      
      
                            filterConfig.getFilterName() + "'");
      
      
                    filterChain.addFilter(filterConfig);
            n
      
      ++
      
        ;
        }

        
      
      
        //
      
      
         Add filters that match on servlet name second
      
      
        for
      
       (
      
        int
      
       i = 0; i < filterMaps.length; i++
      
        ) {

      
      
        //
      
      
                    if (debug >= 2)

      
      
        //
      
      
                        log(" Checking servlet-mapped filter '" +

      
      
        //
      
      
                            filterMaps[i] + "'");
      
      
        if
      
       (!
      
        matchFiltersServlet(filterMaps[i], servletName))
                
      
      
        continue
      
      
        ;
            ApplicationFilterConfig filterConfig 
      
      =
      
         (ApplicationFilterConfig)
                context.findFilterConfig(filterMaps[i].getFilterName());
            
      
      
        if
      
       (filterConfig == 
      
        null
      
      
        ) {

      
      
        //
      
      
                        if (debug >= 2)

      
      
        //
      
      
                            log(" Missing servlet-mapped filter '" +

      
      
        //
      
      
                                filterMaps[i] + "'");
      
      
                ;       
      
        //
      
      
         FIXME - log configuration problem
      
      
        continue
      
      
        ;
            }

      
      
        //
      
      
                    if (debug >= 2)

      
      
        //
      
      
                        log(" Adding servlet-mapped filter '" +

      
      
        //
      
      
                             filterMaps[i] + "'");
      
      
                    filterChain.addFilter(filterConfig);
            n
      
      ++
      
        ;
        }

        
      
      
        //
      
      
         Return the completed filter chain

      
      
        //
      
      
                if (debug >= 2)

      
      
        //
      
      
                    log(" Returning chain with " + n + " filters");
      
      
        return
      
      
         (filterChain);

    }
      
    

--------------------------------------------------------------------------- 

本系列How Tomcat Works系本人原创 

转载请注明出处 博客园 刺猬的温驯 

本人邮箱:   chenying998179 # 163.com ( #改为@

本文链接 http://www.cnblogs.com/chenying99/p/3250342.html

How Tomcat Works(十四)补充


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论