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 下的更多相关文章

  1. how tomcat works 读书笔记 十一 StandWrapper 上

    方法调用序列 下图展示了方法调用的协作图:  这个是前面第五章里,我画的图:  我们再回顾一下自从连接器里  connector.getContainer().invoke(request, resp ...

  2. how tomcat works 读书笔记(二)----------一个简单的servlet容器

    app1 (建议读者在看本章之前,先看how tomcat works 读书笔记(一)----------一个简单的web服务器 http://blog.csdn.net/dlf123321/arti ...

  3. how tomcat works 读书笔记四 tomcat的默认连接器

    事实上在第三章,就已经有了连接器的样子了,只是那仅仅是一个学习工具,在这一章我们会開始分析tomcat4里面的默认连接器. 连接器 Tomcat连接器必须满足下面几个要求 1 实现org.apache ...

  4. How tomcat works 读书笔记十五 Digester库 下

    在这一节里我们说说ContextConfig这个类. 这个类在很早的时候我们就已经使用了(之前那个叫SimpleContextConfig),但是在之前它干的事情都很简单,就是吧context里的co ...

  5. How tomcat works 读书笔记十七 启动tomcat 下

    在上一节中,我们程序的起始位置还是Bootstrap,现在我们通过bat文件来启动这个类. 在分析catalina.bat之前,我们先看看几个简单的我们能用到的dos命令. 基础知识 1 rem 注释 ...

  6. How tomcat works 读书笔记十二 StandardContext 下

    对重载的支持 tomcat里容器对重载功能的支持是依靠Load的(在目前就是WebLoader).当在绑定载入器的容器时 public void setContainer(Container cont ...

  7. how tomcat works 读书笔记 八 载入器下

    载入类 我们看看之前的文章,这一节就从SimpleWrapper的loadServlet讲起. SimpleWrapper.java如下(省略了try catch及其他部分代码) public Ser ...

  8. how tomcat works 读书笔记(一)----------一个简单的webserver

    http协议 若是两个人能正常的说话交流,那么他们间必然有一套统一的语言规则<在网络上server与client能交流也依赖与一套规则,它就是我们说的http规则(超文本传输协议Hypertex ...

  9. how tomcat works 读书笔记(一)----------一个简单的web服务器

    http协议 若是两个人能正常的说话交流,那么他们间必定有一套统一的语言规则<在网络上服务器与客户端能交流也依赖与一套规则,它就是我们说的http规则(超文本传输协议Hypertext tran ...

随机推荐

  1. 【Android应用开发】Android 蓝牙低功耗 (BLE) ( 第一篇 . 概述 . 蓝牙低功耗文档 翻译)

    转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/50515359 参考 :  -- 官方文档 : https://develope ...

  2. SQL 数据库语言分析总结(一)

    SQL语言是被广泛采用的数据库的学习语言,之前在本科的时候已经学习过了,但是后来又忘记了,所以这次简单的总结一下. 分类 交互式sql语言,交互式语言主要是利用一些数据库工具,比如mysql的终端工具 ...

  3. 开源项目——小Q聊天机器人V1.0

    小Q聊天机器人V1.0 http://blog.csdn.net/baiyuliang2013/article/details/51386281 小Q聊天机器人V1.1 http://blog.csd ...

  4. C语言--测试电脑存储模式(大端存储OR小端存储)

    相信大家都知道大端存储和小端存储的概念,这在平时,我们一般不用考虑,但是,在某些场合,这些概念就显得很重要,比如,在 Socket 通信时,我们的电脑是小端存储模式,可是传送数据或者消息给对方电脑时, ...

  5. (NO.00004)iOS实现打砖块游戏(十一):"一闪一闪亮晶晶,我们都是小星星"

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 现在一个基本的游戏逻辑已经搭建好了,但是感觉还是缺点什么呢? 蠢 ...

  6. JAVA之旅(二十六)——装饰设计模式,继承和装饰的区别,LineNumberReader,自定义LineNumberReader,字节流读取操作,I/O复制图片

    JAVA之旅(二十六)--装饰设计模式,继承和装饰的区别,LineNumberReader,自定义LineNumberReader,字节流读取操作,I/O复制图片 一.装饰设计模式 其实我们自定义re ...

  7. Git Bash+EGit在项目中配合使用最常用方法总结(根据场景使用)

    最近在项目中使用Git进行代码管理,之前一直用SVN进行管理,现在谈一谈Git在项目中如何与EGit插件配合使用,高效同步开发. 使用过SVN一段时间的人,初识Git一定感觉很别扭,发现会遇到各种各样 ...

  8. Docker教程:使用docker配置python开发环境

    http://blog.csdn.net/pipisorry/article/details/50808034 Docker的安装和配置 [Docker教程:docker的安装] [Docker教程: ...

  9. iOS中 GCD-Grand Central Dispath 多线程 UI_21

    GCD:Grand Central Dispath "牛逼的中枢调度器";是纯C语言编写的,提供了很多比较强大的函数 GCD:优势 1.目前是苹果主推的线程管理方式 2.它会自动的 ...

  10. 产品打包工具的制作,ant,编译源码,打jar包,打tag,打war包,备份release版本等

    1.  在进行打包工具的制作前,需要准备的软件有: svnant-1.3.1 作用是让ant和svn相关联 apache-ant-1.9.7 需要设置ant_home,path,我的配置是: ANT_ ...