君子博学而日参省乎己 则知明而行无过矣

博客园 首页 新随笔 联系 订阅 管理

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

posted on 2013-08-11 00:06  刺猬的温驯  阅读(494)  评论(0编辑  收藏  举报