首页 > 代码库 > how tomcat works 读书笔记 十一 StandWrapper 下

how tomcat works 读书笔记 十一 StandWrapper 下

StandardWrapperValve

StandardWrapperValve是StandardWrapper的基础阀,主要完成了三个工作。
1 调用StandardWrapper的allocate的方法来获得该StandardWrapper所表示的servlet实例
2 执行与该servelt相关联的全部过滤器
3 调用servlet的service方法

其中第二三步可以细分为
  调用它的 private createFilterChain 方法获得过滤链
  调用过滤器链的 doFilter 方法。这里面就调用了servlet 的 service方法
  释放过滤器链
  调用包装器的deallocate方法

  如果Servlet无法使用了,调用包装器的 unload 方法


我们看看大致的代码片段
// Allocate a servlet instance to process this request
try {
    if (!unavailable) {
    servlet = wrapper.allocate();
    }
}
...
// Acknowlege the request
try {
    response.sendAcknowledgement();
}
...
// Create the filter chain for this request
    ApplicationFilterChain filterChain = createFilterChain(request,servlet);
// Call the filter chain for this request// This also calls the servlet's servicet() method
try {
    String jspFile = wrapper.getJspFile();
    if (jspFile != null)
    sreq.setAttribute(Globals.JSP_FILE_ATTR, jspFile);
    else
    sreq.removeAttribute(Globals.JSP_FILE_ATTR);
    if ((servlet != null) && (filterChain != null)) {
    filterChain.doFilter(sreq, sres);
    }
    sreq.removeAttribute(Globals.JSP_FILE_ATTR);
}
...
// Release the filter chain (if any) for this request
try {
    if (filterChain != null)
        filterChain.release();
}
...
// Deallocate the allocated servlet instance
try {
    if (servlet != null) {
        wrapper.deallocate(servlet);
    }
}
...
// If this servlet has been marked permanently unavailable,
// unload it and release this instance
try {
    if ((servlet != null) && (wrapper.getAvailable() ==Long.MAX_VALUE)) {
        wrapper.unload();
    }
}


看了上面的代码,大家应该能看出来最复杂的部分有两处
其一 ApplicationFilterChain filterChain = createFilterChain(request,servlet);
其二 filterChain.doFilter(sreq, sres);
一步一步来。

FilterDef类

这个类的全名应该是FilterDefinition,过滤器描述类。
里面包含了一个Filter的filterClass,filterName等基本信息,及get/set方法。
这里面的属性,我们可以看看这个
    /**
     * The set of initialization parameters for this filter, keyed by
     * parameter name.
     */
    private Map<String, String> parameters = new HashMap<String, String>();
用HashMap存储了初始化参数,它有get方法,增加属性的方法是addInitParameter(String name, String value)。

ApplicationFilterConfig类

org.apache.catalina.core.ApplicationFilterConfig 实现了javax.servlet.FilterConfig 接口。ApplicationFilterConfig 负责管理 web应用程序启动的时候创建的过滤器实例。
其构造函数如下:
public ApplicationFilterConfig(Context context, FilterDef filterDef)
                                 throws ClassCastException, ClassNotFoundException,IllegalAccessException, InstantiationException, ServletException
在这里我们主要谈谈它的getFilter方法,该方法的功能其实就是加载过滤器类并初始化它。
首先从filterDef里面获得filterClass;
        String filterClass = filterDef.getFilterClass();
        ClassLoader classLoader = null;
        if (filterClass.startsWith("org.apache.catalina."))
            classLoader = this.getClass().getClassLoader();
        else
            classLoader = context.getLoader().getClassLoader();
    .....
            Class<?> clazz = classLoader.loadClass(filterClass);
        this.filter = (Filter) clazz.newInstance();
        filter.init(this);
        return (this.filter);
还是没有什么要说的。


ApplicationFilterChain类

StandardWrapperValve 类中的 invoke 方法创建一个该类的实例并且调用它的 doFilter 方法。ApplicationFilterChain类的doFilter(其实是internalDoFilter)调用该链中第一个过滤器的 doFilter 方法。
ApplicationFilterChain类中,有一个ApplicationFilterConfig的引用

    private ArrayList<ApplicationFilterConfig> filters = new ArrayList<ApplicationFilterConfig>();

看到了把,数组形式来存放链条。

典型的责任链模式。

Filter 接口中doFilter 方法的签名如下:
public void doFilter(ServletRaquest request, ServletResponse response,FilterChain chain)
            throws java.io.IOException, ServletException
在ApplicationFilterChain的doFilter方法中,它会将自己作为第三个参数传递给它。
我们看一个Filter实现类的例子
public void doFilter(ServletRequest request, ServletResponse response,
                    FilterChain chain) throws IOException, ServletException {
    // do something here
    ...
    chain.doFilter(request, response);
}
循环往复了
此处的循环不是那么容易理解,建议参考鄙人的另一篇博客

http://blog.csdn.net/dlf123321/article/details/40078583


等所有的Filter都执行完了,就是下面的代码

           if ((request instanceof HttpServletRequest) &&
                (response instanceof HttpServletResponse)) {
                servlet.service((HttpServletRequest) request,
                                (HttpServletResponse) response);
            } else {
                servlet.service(request, response);
            }

什么时候Filter才算执行完了呢?

 private Iterator<ApplicationFilterConfig> iterator = null;

....

 if (this.iterator == null)
            this.iterator = filters.iterator();

        // Call the next filter if there is one
        if (this.iterator.hasNext()) {

                    //执行filter

       }...      //调用servlet的service的代码块...


应用程序

和之前的几章没有什么区别,不再赘述。






how tomcat works 读书笔记 十一 StandWrapper 下