StrutsPrepareAndExecuteFilter剖析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/kk121150/article/details/78169677

FilterDispatcher是struts2.0.x到2.1.2版本的核心过滤器.!
StrutsPrepareAndExecuteFilter是自2.1.3开始就替代了FilterDispatcher的

方法摘要

 void destroy() 
           继承自Filter,用于资源释放
 void doFilter(ServletRequest req,ServletResponse res,FilterChain chain) 
           继承自Filter,执行方法
 void init(FilterConfig filterConfig) 
           继承自Filter,初始化参数
protected  void postInit(Dispatcher dispatcher,FilterConfig filterConfig) 
          Callback for post initialization(一个空的方法,用于方法回调初始化)
属性摘要

protected  List<Pattern> excludedPatterns 
           
protected  ExecuteOperations execute 
           
protected  PrepareOperations prepare 

StrutsPrepareAndExecuteFilter类继承与Filter,所以大体结构和普通Filter类似:

public class StrutsPrepareAndExecuteFilter implements StrutsStatics, Filter {
    protected PrepareOperations prepare;
    protected ExecuteOperations execute;
    protected List<Pattern> excludedPatterns = null;

    public void init(FilterConfig filterConfig) {
        Dispatcher dispatcher = null;
        try {
            FilterHostConfig config = new FilterHostConfig(filterConfig); //读取配置文件信息,封装到config
            dispatcher = init.initDispatcher(config); //根据config创建dispatcher对象
            ...
            prepare = new PrepareOperations(dispatcher); //根据dispatcher创建prepare对象(包括准备的一些操作)
            execute = new ExecuteOperations(dispatcher); //根据dispatcher创建execute对象(包括执行的一些操作)
            postInit(dispatcher, filterConfig); //回调空的postInit函数
        } finally {
            ...
        }
    }

    /**
     * Callback for post initialization
     */
    protected void postInit(Dispatcher dispatcher, FilterConfig filterConfig) {
    }

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain){

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        try {

                prepare.createActionContext(request, response); //创建ActionContext对象!!!存储request、session、application、parameters等相关信息

                execute.executeAction(request, response, mapping);  //执行ActionContext(创建ActionProxy对象并嵌入一系列的拦截器,调用Action)

            }
        } finally {

        }
    }

    public void destroy() {
        prepare.cleanupDispatcher();
    }

}

Filter方法调用顺序为由init—>doFilter—>destroy顺序调用。

init方法

public void init(FilterConfig filterConfig) throws ServletException {    
    //创建一个InitOperations初始化操作的对象    
     InitOperations init = new InitOperations();    
     try {    
         //封装filterConfig,其中有个主要方法getInitParameterNames将参数名字以String格式存储在List中    
         FilterHostConfig config = new FilterHostConfig(filterConfig);    
         // 初始化struts内部日志      
         init.initLogging(config);    
         //创建dispatcher对象,并读取配置文件       
         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 {    
         init.cleanup();    
     }    
 }    


其中的 FilterHostConfig,
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);    
    }    
    
    //返回初始化参数名的List    
    public Iterator<String> getInitParameterNames() {    
        return MakeIterator.convert(config.getInitParameterNames());    
    }    
    
    public ServletContext getServletContext() {    
        return config.getServletContext();    
    }    
}    

创建并初始化Dispatcher 


public Dispatcher initDispatcher(HostConfig filterConfig) {    
    // 创建dispatcher对象,将参数传递dispatcher全局变量    
    Dispatcher dispatcher = createDispatcher(filterConfig);    
    // 初始化配置文件/读取配置文件    
    dispatcher.init();    
    return dispatcher;    
} 
创建Dispatcher,会读取 filterConfig 中的配置信息,将配置信息解析出来,封装成为一个Map,然后根绝servlet上下文和参数Map构造Dispatcher :

createDispatcher方法。创建Dispatcher,会读取 filterConfig中的配置信息。

private Dispatcher createDispatcher(HostConfig filterConfig) {    
    Map<String, String> params = new HashMap<String, String>();    
    // 获得在web.xml中所有的配置文件,将参数放入params Map集合中    
    for (Iterator e = filterConfig.getInitParameterNames(); e.hasNext();) {    
        String name = (String) e.next();    
        String value = filterConfig.getInitParameter(name);    
        params.put(name, value);    
    }    
    // 创建Dispatcher 对象,将ServletContext(),将参数赋给Dispatcher的全局私有变量中    
    return new Dispatcher(filterConfig.getServletContext(), params);    
}   

Disptcher的init方法,init方法里就是初始读取一些配置文件等,加载struts2的相关配置文件,将按照顺序逐一加载:default.properties,struts-default.xml,struts-plugin.xml,struts.xml,

 *初始化过程中依次加载如下配置文件 
 */  
public void init() {  
  
        if (configurationManager == null) {  
            configurationManager = new ConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME);  
        }  
  
        try {  
            //加载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_CheckConfigurationReloading(container);  
            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);  
        }  
    }  

doFilter方法
     doFilter是过滤器的执行方法,它拦截提交的HttpServletRequest请求,HttpServletResponse响应,作为strtus2的核心拦截器,在doFilter里面到底做了哪些工作,我们将逐行解读其源码,源码如下:
 public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {  
     //父类向子类转:强转为http请求、响应  
     HttpServletRequest request = (HttpServletRequest) req;  
     HttpServletResponse response = (HttpServletResponse) res;  
  
     try {  
         //设置编码和国际化  
         prepare.setEncodingAndLocale(request, response);  
          //创建Action上下文(重点)  
         prepare.createActionContext(request, response);  
         prepare.assignDispatcherToThread();  
if ( excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) {  
    chain.doFilter(request, response);  
} else {  
    request = prepare.wrapRequest(request);  
    ActionMapping mapping = prepare.findActionMapping(request, response, true);  
    if (mapping == null) {  
        boolean handled = execute.executeStaticResourceRequest(request, response);  
        if (!handled) {  
            chain.doFilter(request, response);  
        }  
    } else {  
        execute.executeAction(request, response, mapping);  
    }  
}  
     } finally {  
         prepare.cleanupRequest(request);  
     }  
 }  

Action上下文创建(重点)
       ActionContext是一个容器,这个容易主要存储request、session、application、parameters等相关信息.ActionContext是一个线程的本地变量,这意味着不同的action之间不会共享ActionContext,所以也不用考虑线程安全问题。其实质是一个Map,key是标示request、session、……的字符串,值是其对应的对象:

//创建ActionContext,初始化thread local     
public ActionContext createActionContext(HttpServletRequest request, HttpServletResponse response) {    
    ActionContext ctx;    
    Integer counter = 1;    
    Integer oldCounter = (Integer) request.getAttribute(CLEANUP_RECURSION_COUNTER);    
    if (oldCounter != null) {    
        counter = oldCounter + 1;    
    }    
        
    //从ThreadLocal中获取此ActionContext变量    
    ActionContext oldContext = ActionContext.getContext();    
    if (oldContext != null) {    
        // detected existing context, so we are probably in a forward    
        ctx = new ActionContext(new HashMap<String, Object>(oldContext.getContextMap()));    
    } else {    
        ValueStack stack = dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack();    
        stack.getContext().putAll(dispatcher.createContextMap(request, response, null, servletContext));    
        //stack.getContext()返回的是一个Map<String,Object>,根据此Map构造一个ActionContext      
        ctx = new ActionContext(stack.getContext());    
    }    
    request.setAttribute(CLEANUP_RECURSION_COUNTER, counter);    
        
    //将ActionContext保存ThreadLocal      
    ActionContext.setContext(ctx);    
    return ctx;    
}   



未完。。。


 
 
 
 
 

猜你喜欢

转载自blog.csdn.net/kk121150/article/details/78169677