• 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);
    }
    循环往复了
    此处的循环不是那么easy理解,建议參考鄙人的还有一篇博客

    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的代码块
    ...
    


    应用程序

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






  • 相关阅读:
    【2】Java包装类
    【1】Java异常
    【10】Java多态:内部类
    【9】Java多态:接口
    【8】Java多态:抽象类(abstract关键字)
    【7】Java多态:向上转型、向下转型、instanceof运算符
    【6】Java单例模式
    元素定位工具:Chrome浏览器ChroPath插件
    linux添加环境变量
    php导出数据到多个csv并打包压缩
  • 原文地址:https://www.cnblogs.com/lxjshuju/p/7124562.html
Copyright © 2020-2023  润新知