zoukankan      html  css  js  c++  java
  • 朝花夕拾之Struts2的StrutsPrepareAndExecuteFilter的初始化过程

    在使用Struts2的时候,我们都会在项目中的web.xml这样定义:

    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping>
    

      这样写的意思是让所有的请求都经过这个过滤器(如果不想所有的请求都经过该过滤器,只需要更改url-pattern)。

      而在早期的Struts2(2.1.0-2.1.3)的时候,并不是使用的StrutsPrepareAndExecuteFilter这个过滤器,而是使用FilterDispather,那么他们有什么区别呢? 

    <filter>
       <filter-name>struts2</filter-name>
       <filter-class>
         org.apache.struts2.dispatcher.FilterDispatcher
       </filter-class>
    </filter>
    

      应该知道如果我们自己定义过滤器的话, 是要放在strtus2的过滤器之前的, 如果放在struts2过滤器之后,你自己的过滤器对action的过滤作用就废了,不会有效!除非你是访问jsp/html! 
    那我现在有需求, 我必须使用Action的环境,而又想在执行action之前拿filter做一些事, 用FilterDispatcher是做不到的.! 
    那么StrutsPrepareAndExecuteFilter可以把他拆分成StrutsPrepareFilter和StrutsExecuteFilter,可以在这两个过滤器之间加上我们自己的过滤器.! 

      我们来看一下StrutsPrepareAndExecuteFilter这个类:

    void init(FilterConfig filterConfig)    //继承自Filter,过滤器的初始化
    void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)   //继承自Filter 执行过滤器
    void destory()  //继承Filter
    postInit(dispatcher, filterConfig);   //回掉方法

      在web容器一启动,就会去执行init方法:

    public void init(FilterConfig filterConfig) throws ServletException {
            InitOperations init = new InitOperations();
            Dispatcher dispatcher = null;
            try {
                //封装filterConfig,其中有个主要方法getInitParameterNames将参数名字以String格式存储在List中
                FilterHostConfig config = new FilterHostConfig(filterConfig);
                //初始化struts内部日志
                init.initLogging(config);
                //创建dispatcher ,并初始化
                dispatcher = init.initDispatcher(config);
                init.initStaticContentLoader(config, dispatcher);
                //初始化类属性:prepare 、execute
                prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);
                execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);
                this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);
                //回调空的postInit方法
                postInit(dispatcher, filterConfig);
            } finally {
                if (dispatcher != null) {
                    dispatcher.cleanUpAfterInit();
                }
                init.cleanup();
            }
        }
    

      FilterHostConfig用来将FilterConfig封装

    public class FilterHostConfig implements HostConfig {
    
        private FilterConfig config;
        //构造方法
        public FilterHostConfig(FilterConfig config) {
            this.config = config;
        }
        //根据init-param配置的param-name获取param-value的值  
        public String getInitParameter(String key) {
            return config.getInitParameter(key);
        }
        //返回初始化参数名的迭代器 
        public Iterator<String> getInitParameterNames() {
            return MakeIterator.convert(config.getInitParameterNames());
        }
        //返回Servlet上下文
        public ServletContext getServletContext() {
            return config.getServletContext();
        }
    }
    

      getInitParameterNames()是这个类的核心方法,将Filter初始化参数名称有枚举类型转为Iterator。此类的主要作为是对filterConfig 封装。

    看下StrutsPrepareAndExecuteFilter中init方法中dispatcher = init.initDispatcher(config);这是初始化dispatcher的,是通过init对象的initDispatcher方法来初始化的,init是InitOperations类的对象,我们看看InitOperations中initDispatcher方法:

      public Dispatcher initDispatcher( HostConfig filterConfig ) {
             Dispatcher dispatcher = createDispatcher(filterConfig);
             dispatcher.init();
            return dispatcher;
       }

      

    private Dispatcher createDispatcher( HostConfig filterConfig ) {
            //存放参数的Map
            Map<String, String> params = new HashMap<String, String>();
            //将参数存放到Map
            for ( Iterator e = filterConfig.getInitParameterNames(); e.hasNext(); ) {
                String name = (String) e.next();
                String value = filterConfig.getInitParameter(name);
                params.put(name, value);
            }
            //根据servlet上下文和参数Map构造Dispatcher 
            return new Dispatcher(filterConfig.getServletContext(), params);
        }
    

      这样dispatcher对象创建完成,接着就是dispatcher对象的初始化,打开Dispatcher类,看到它的init方法如下:

    public void init() {
    
            if (configurationManager == null) {
                configurationManager = createConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME);
            }
    
            try {
                init_FileManager();
                //加载org/apache/struts2/default.properties
                init_DefaultProperties(); // [1]
                //加载struts-default.xml,struts-plugin.xml,struts.xml
                init_TraditionalXmlConfigurations(); // [2]
                init_LegacyStrutsProperties(); // [3]
                //用户自己实现的ConfigurationProviders类 
                init_CustomConfigurationProviders(); // [5]
                //Filter的初始化参数 
                init_FilterInitParameters() ; // [6]
                init_AliasStandardObjects() ; // [7]
    
                Container container = init_PreloadConfiguration();
                container.inject(this);
                init_CheckWebLogicWorkaround(container);
    
                if (!dispatcherListeners.isEmpty()) {
                    for (DispatcherListener l : dispatcherListeners) {
                        l.dispatcherInitialized(this);
                    }
                }
            } catch (Exception ex) {
                if (LOG.isErrorEnabled())
                    LOG.error("Dispatcher initialization failed", ex);
                throw new StrutsException(ex);
            }
        }
    

      这里主要是加载一些配置文件的,将按照顺序逐一加载:default.properties,struts-default.xml,struts-plugin.xml,struts.xml,……关于文件是如何加载的,大家可以自己取看源文件,主要是由xwork核心类加载的,代码在xwork-coresrcmainjavacomopensymphonyxwork2configproviders包里面。

  • 相关阅读:
    “无法从http://XXX/XXX.svc?wsdl获取元数据”错误的解决方法
    闹洞房小游戏
    第3章 Oracle实例的管理
    公积金余额查询电话
    人要有忧患意识
    第0章 Oracle的安装及相关配置
    第5章 重做日志文件
    oracle体系结构视频学习笔记
    编写存储过程实现查询mysql数据库中的表名并删除表中的数据
    第6章 表空间和数据文件的管理
  • 原文地址:https://www.cnblogs.com/dengyuanqi/p/7645222.html
Copyright © 2011-2022 走看看