devil20 发表于 2015-8-12 07:06:10

How Tomcat Works(十四)补充

  在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 + "'");
if (!matchFiltersURL(filterMaps, requestPath))
continue;
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
context.findFilterConfig(filterMaps.getFilterName());
if (filterConfig == null) {
//                if (debug >= 2)
//                  log(" Missing path-mapped filter '" +
//                        filterMaps + "'");
;       // 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 + "'");
if (!matchFiltersServlet(filterMaps, servletName))
continue;
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
context.findFilterConfig(filterMaps.getFilterName());
if (filterConfig == null) {
//                if (debug >= 2)
//                  log(" Missing servlet-mapped filter '" +
//                        filterMaps + "'");
;       // FIXME - log configuration problem
continue;
}
//            if (debug >= 2)
//                log(" Adding servlet-mapped filter '" +
//                     filterMaps + "'");
            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.iyunv.com/chenying99/p/3250342.html
页: [1]
查看完整版本: How Tomcat Works(十四)补充