• StrutsPrepareAndExecuteFilter


    StrutsPrepareAndExecuteFilter

    分类: 框架

    原文转载自:http://www.iteye.com/topic/829843 

    一、概述

         Struts2的核心是一个Filter,Action可以脱离web容器,那么是什么让http请求和action关联在一起的,下面我们深入源码来分析下Struts2是如何工作的。

    FilterDispatcher API 写道
    Deprecated. Since Struts 2.1.3, use StrutsPrepareAndExecuteFilter instead or StrutsPrepareFilter and StrutsExecuteFilter if needing using the ActionContextCleanUp filter in addition to this one

     

         鉴于常规情况官方推荐使用StrutsPrepareAndExecuteFilter替代FilterDispatcher,我们此文 将剖析StrutsPrepareAndExecuteFilter,其在工程中作为一个Filter配置在web.xml中,配置如下:

    Xml代码  收藏代码
    1. filter  filter-name </ filter-name  filter-class ></ filter-class > </ filter  filter-mapping  filter-name </ filter-name  url-pattern </ url-pattern  </ filter-mapping   
    [xml] view plaincopy
     
    1. <filter> <filter-name></filter-name> <filter-class></filter-class> </filter> <filter-mapping> <filter-name></filter-name> <url-pattern></url-pattern> </filter-mapping>  

     

    二、源码属性方法简介

        下面我们研究下StrutsPrepareAndExecuteFilter源码,类的主要信息如下:

     

    属性摘要
    protected  List<Pattern > excludedPatterns 
               
    protected  ExecuteOperations execute 
               
    protected  PrepareOperations prepare 
               

     

        StrutsPrepareAndExecuteFilter与普通的Filter并无区别,方法除继承自Filter外,仅有一个回调方法,第三部分我 们将按照Filter方法调用顺序,由init—>doFilter—>destroy顺序地分析源码。

    方法摘要
     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(一个空的方法,用于方法回调初始化)

     

    三、源码剖析    

     

        1、init方法

             init是Filter第一个运行的方法,我们看下struts2的核心Filter在调用init方法初始化时做哪些工作:

    Java代码  收藏代码
    1.   public void throws  new  try  //封装filterConfig,其中有个主要方法getInitParameterNames将参数名字以String格式存储在List中  new  // 初始化struts内部日志  //<strong>创建dispatcher ,并初始化,这部分下面我们重点分析,初始化时加载那些资源</strong>  //初始化类属性:prepare 、execute   new new this  //回调空的postInit方法  finally   }  
    [java] view plaincopy
     
    1.  publicvoidthrows new try //封装filterConfig,其中有个主要方法getInitParameterNames将参数名字以String格式存储在List中 new // 初始化struts内部日志 //<strong>创建dispatcher ,并初始化,这部分下面我们重点分析,初始化时加载那些资源</strong> //初始化类属性:prepare 、execute  new new this //回调空的postInit方法 finally  }  

     

       首先看下FilterHostConfig ,源码如下:

     

    Java代码  收藏代码
    1. public class implements  private       *构造函数    
    2.      */  public  this       *  根据init-param配置的param-name获取param-value的值  
    3.      */  public  return           *  返回初始化参数名的List  
    4.      */  public  return  public  return  }  
    [java] view plaincopy
     
    1. publicclassimplements private      *构造函数   
    2.      */ public this      *  根据init-param配置的param-name获取param-value的值 
    3.      */ public return          *  返回初始化参数名的List 
    4.      */ public return public return }  

       只有短短的几行代码,getInitParameterNames是这个类的核心,将Filter初始化参数名称有枚举类型转为Iterator。此类的主要作为是对filterConfig 封装。

     

     

        重点来了,创建并初始化Dispatcher      

    Java代码  收藏代码
    1. public  return     }  
    [java] view plaincopy
     
    1. public return    }  

         创建Dispatcher,会读取 filterConfig 中的配置信息,将配置信息解析出来,封装成为一个Map,然后根绝servlet上下文和参数Map构造Dispatcher :

    Java代码  收藏代码
    1. private  new  for  return new      }  
    [java] view plaincopy
     
    1. private new for returnnew     }  

      Dispatcher初始化,加载struts2的相关配置文件,将按照顺序逐一加载:default.properties,struts-default.xml,struts-plugin.xml,struts.xml,……

     

    Java代码  收藏代码
    1. /**  
    2. *初始化过程中依次加载如下配置文件  
    3. */  public void  if null  new try    
    4.   
    5.   
    6.   
    7.   
    8.   
    9.   
    10.   
    11.   
    12.   
    13. this  if  for  this  catch  if    throw new      }  
    [java] view plaincopy
     
    1. /** 
    2. *初始化过程中依次加载如下配置文件 
    3. */ publicvoid ifnull new try   
    4.   
    5.   
    6.   
    7.   
    8.   
    9.   
    10.   
    11.   
    12.   
    13. this if for this catch if thrownew     }  

     

       初始化default.properties,具体的初始化操作在DefaultPropertiesProvider类中

      

    Java代码  收藏代码
    1. private void  new     }  
    [java] view plaincopy
     
    1. privatevoid new    }  

        

       下面我们看下DefaultPropertiesProvider类源码:

     

    Java代码  收藏代码
    1. public void  throws  null  try  new );  
    2. catch  throw new       }  
    [java] view plaincopy
     
    1. publicvoid throws null try new);  
    2. catch thrownew     }  

     

       其他的我们再次省略,大家可以浏览下各个初始化操作都加载了那些文件

     


    3、doFilter方法

     

         doFilter是过滤器的执行方法,它拦截提交的HttpServletRequest请求,HttpServletResponse响应,作为strtus2的核心拦截器,在doFilter里面到底做了哪些工作,我们将逐行解读其源码,源码如下:

     

    Java代码  收藏代码
    1.   public void throws    
    2. try    
    3.   
    4. if null  else  true  if null  boolean  if  else  finally   }  
    [java] view plaincopy
     
    1.  publicvoidthrows   
    2. try   
    3.   
    4. ifnull else true ifnull boolean if else finally  }  

     

        setEncodingAndLocale调用了dispatcher方法的prepare方法:

     

    Java代码  收藏代码
    1. /**  
    2.      * Sets the request encoding and locale on the response  
    3.      */  public void     }  
    [java] view plaincopy
     
    1. /** 
    2.      * Sets the request encoding and locale on the response 
    3.      */ publicvoid     }  

     

       下面我们看下prepare方法,这个方法很简单只是设置了encoding 、locale ,做的只是一些辅助的工作:

    Java代码  收藏代码
    1. public void  null  if null  null  if null  if null  try  catch     if null  if  );       }  
    [java] view plaincopy
     
    1. publicvoid null ifnull null ifnull ifnull try catch ifnull if );      }  

     

       Action上下文创建(重点)

     

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

    Java代码  收藏代码
    1. static new  Map<String, Object> context;  
    [java] view plaincopy
     
    1. staticnew Map<String, Object> context;  

     
       下面我们看下如何创建action上下文的,代码如下:

     

    Java代码  收藏代码
    1. /**  
    2. *创建Action上下文,初始化thread local  
    3. */  public ;  
    4. if null  ;  
    5.   
    6. if null    
    7. new new  else  class null   
    8. new    
    9. return  }  
    [java] view plaincopy
     
    1. /** 
    2. *创建Action上下文,初始化thread local 
    3. */ public ;  
    4. ifnull ;  
    5.   
    6. ifnull   
    7. newnew else class null   
    8. new   
    9. return }  

     

        上面代码中dispatcher.createContextMap,如何封装相关参数:

     

    Java代码  收藏代码
    1. public   
    2. new    
    3. new    
    4. new    
    5. new    
    6. if null  return  }  
    [java] view plaincopy
     
    1. public   
    2. new   
    3. new   
    4. new   
    5. new   
    6. ifnull return }  

     

     我们简单看下RequestMap,其他的省略。RequestMap类实现了抽象Map,故其本身是一个Map,主要方法实现:

    Java代码  收藏代码
    1. //map的get实现  public  return  //map的put实现  public  null  return  }  
    [java] view plaincopy
     
    1. //map的get实现 public return //map的put实现 public null return }  

     

       下面是源码展示了如何执行Action控制器:

     

    Java代码  收藏代码
    1. public voidthrows  public void throws    
    2.   
    3. boolean null  if  if null  if null    try    
    4.   
    5.   
    6.   
    7. class true false    
    8.   
    9. if null  else    
    10. if  catch    
    11. if  if null   + request.getQueryString();  
    12.   else    catch  finally      }  
    [java] view plaincopy
     
    1. publicvoidthrows publicvoid throws   
    2.   
    3. booleannull if ifnull ifnull try   
    4.   
    5.   
    6.   
    7. class truefalse   
    8.   
    9. ifnull else   
    10. if catch   
    11. if ifnull  + request.getQueryString();  
    12. else catch finally     }  

     

       文中对如何解析Struts.xml,如何将URL与action映射匹配为分析,有需要的我后续补全,因为 StrutsXmlConfigurationProvider继承XmlConfigurationProvider,并在register方法回调父 类的register,有兴趣的可以深入阅读下下XmlConfigurationProvider源码:

     

    Java代码  收藏代码
    1. public void throws  if null class class new  public throws  return    
    2. super     }  
    [java] view plaincopy
     
    1. publicvoidthrows ifnullclass classnew publicthrows return   
    2. super    }  

     

     

         struts2-core-2.2.1.jar包中struts-2.1.7.dtd对于Action的定义如下:

    Xml代码  收藏代码
    1. <!ELEMENT action (param|result|interceptor-ref|exception-mapping)*    
    [xml] view plaincopy
     
    1. <!ELEMENT action (param|result|interceptor-ref|exception-mapping)*> >  

        从上述DTD中可见Action元素可以含有name 、class 、method 、converter 属性。

     

       XmlConfigurationProvider解析struts.xml配置的Action元素:

    Java代码  收藏代码
    1. protected void throws  );  
    2. );  
    3. );  
    4. if null      
    5. ) ? methodName.trim() :  null    
    6.   
    7. if    
    8.              className = packageContext.getDefaultClassRef();  
    9.          } else {  
    10.              className = ActionSupport.class.getName();  
    11.          }*/  else  if  if  return  try  catch  throw new   new if  ) :  ) + name +     }  
    [java] view plaincopy
     
    1. protectedvoidthrows );  
    2. );  
    3. );  
    4. ifnull   
    5. ) ? methodName.trim() : null   
    6.   
    7. if   
    8.              className = packageContext.getDefaultClassRef(); 
    9.          } else { 
    10.              className = ActionSupport.class.getName(); 
    11.          }*/ else if if return try catch thrownew new if ) : ) + name +   }  

     

     

         工作中不涉及Struts2,本周工作有个2天的空档期,稍微看了下struts2的文档,写了个demo,从源码的角度研究了下运行原理,如有分析不当请指出,我后续逐步完善更正,大家共同提高。

     一、概述

         Struts2的核心是一个Filter,Action可以脱离web容器,那么是什么让http请求和action关联在一起的,下面我们深入源码来分析下Struts2是如何工作的。

    FilterDispatcher API 写道
    Deprecated. Since Struts 2.1.3, use StrutsPrepareAndExecuteFilter instead or StrutsPrepareFilter and StrutsExecuteFilter if needing using the ActionContextCleanUp filter in addition to this one

     

         鉴于常规情况官方推荐使用StrutsPrepareAndExecuteFilter替代FilterDispatcher,我们此文 将剖析StrutsPrepareAndExecuteFilter,其在工程中作为一个Filter配置在web.xml中,配置如下:

    Xml代码  收藏代码
    1. filter  filter-name </ filter-name  filter-class ></ filter-class > </ filter  filter-mapping  filter-name </ filter-name  url-pattern </ url-pattern  </ filter-mapping   
    [xml] view plaincopy
     
    1. <filter> <filter-name></filter-name> <filter-class></filter-class> </filter> <filter-mapping> <filter-name></filter-name> <url-pattern></url-pattern> </filter-mapping>  

     

    二、源码属性方法简介

        下面我们研究下StrutsPrepareAndExecuteFilter源码,类的主要信息如下:

     

    属性摘要
    protected  List<Pattern > excludedPatterns 
               
    protected  ExecuteOperations execute 
               
    protected  PrepareOperations prepare 
               

     

        StrutsPrepareAndExecuteFilter与普通的Filter并无区别,方法除继承自Filter外,仅有一个回调方法,第三部分我 们将按照Filter方法调用顺序,由init—>doFilter—>destroy顺序地分析源码。

    方法摘要
     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(一个空的方法,用于方法回调初始化)

     

    三、源码剖析    

     

        1、init方法

             init是Filter第一个运行的方法,我们看下struts2的核心Filter在调用init方法初始化时做哪些工作:

    Java代码  收藏代码
    1.   public void throws  new  try  //封装filterConfig,其中有个主要方法getInitParameterNames将参数名字以String格式存储在List中  new  // 初始化struts内部日志  //<strong>创建dispatcher ,并初始化,这部分下面我们重点分析,初始化时加载那些资源</strong>  //初始化类属性:prepare 、execute   new new this  //回调空的postInit方法  finally   }  
    [java] view plaincopy
     
    1.  publicvoidthrows new try //封装filterConfig,其中有个主要方法getInitParameterNames将参数名字以String格式存储在List中 new // 初始化struts内部日志 //<strong>创建dispatcher ,并初始化,这部分下面我们重点分析,初始化时加载那些资源</strong> //初始化类属性:prepare 、execute  new new this //回调空的postInit方法 finally  }  

     

       首先看下FilterHostConfig ,源码如下:

     

    Java代码  收藏代码
    1. public class implements  private       *构造函数    
    2.      */  public  this       *  根据init-param配置的param-name获取param-value的值  
    3.      */  public  return           *  返回初始化参数名的List  
    4.      */  public  return  public  return  }  
    [java] view plaincopy
     
    1. publicclassimplements private      *构造函数   
    2.      */ public this      *  根据init-param配置的param-name获取param-value的值 
    3.      */ public return          *  返回初始化参数名的List 
    4.      */ public return public return }  

       只有短短的几行代码,getInitParameterNames是这个类的核心,将Filter初始化参数名称有枚举类型转为Iterator。此类的主要作为是对filterConfig 封装。

     

     

        重点来了,创建并初始化Dispatcher      

    Java代码  收藏代码
    1. public  return     }  
    [java] view plaincopy
     
    1. public return    }  

         创建Dispatcher,会读取 filterConfig 中的配置信息,将配置信息解析出来,封装成为一个Map,然后根绝servlet上下文和参数Map构造Dispatcher :

    Java代码  收藏代码
    1. private  new  for  return new      }  
    [java] view plaincopy
     
    1. private new for returnnew     }  

      Dispatcher初始化,加载struts2的相关配置文件,将按照顺序逐一加载:default.properties,struts-default.xml,struts-plugin.xml,struts.xml,……

     

    Java代码  收藏代码
    1. /**  
    2. *初始化过程中依次加载如下配置文件  
    3. */  public void  if null  new try    
    4.   
    5.   
    6.   
    7.   
    8.   
    9.   
    10.   
    11.   
    12.   
    13. this  if  for  this  catch  if    throw new      }  
    [java] view plaincopy
     
    1. /** 
    2. *初始化过程中依次加载如下配置文件 
    3. */ publicvoid ifnull new try   
    4.   
    5.   
    6.   
    7.   
    8.   
    9.   
    10.   
    11.   
    12.   
    13. this if for this catch if thrownew     }  

     

       初始化default.properties,具体的初始化操作在DefaultPropertiesProvider类中

      

    Java代码  收藏代码
    1. private void  new     }  
    [java] view plaincopy
     
    1. privatevoid new    }  

        

       下面我们看下DefaultPropertiesProvider类源码:

     

    Java代码  收藏代码
    1. public void  throws  null  try  new );  
    2. catch  throw new       }  
    [java] view plaincopy
     
    1. publicvoid throws null try new);  
    2. catch thrownew     }  

     

       其他的我们再次省略,大家可以浏览下各个初始化操作都加载了那些文件

     


    3、doFilter方法

     

         doFilter是过滤器的执行方法,它拦截提交的HttpServletRequest请求,HttpServletResponse响应,作为strtus2的核心拦截器,在doFilter里面到底做了哪些工作,我们将逐行解读其源码,源码如下:

     

    Java代码  收藏代码
    1.   public void throws    
    2. try    
    3.   
    4. if null  else  true  if null  boolean  if  else  finally   }  
    [java] view plaincopy
     
    1.  publicvoidthrows   
    2. try   
    3.   
    4. ifnull else true ifnull boolean if else finally  }  

     

        setEncodingAndLocale调用了dispatcher方法的prepare方法:

     

    Java代码  收藏代码
    1. /**  
    2.      * Sets the request encoding and locale on the response  
    3.      */  public void     }  
    [java] view plaincopy
     
    1. /** 
    2.      * Sets the request encoding and locale on the response 
    3.      */ publicvoid     }  

     

       下面我们看下prepare方法,这个方法很简单只是设置了encoding 、locale ,做的只是一些辅助的工作:

    Java代码  收藏代码
    1. public void  null  if null  null  if null  if null  try  catch     if null  if  );       }  
    [java] view plaincopy
     
    1. publicvoid null ifnull null ifnull ifnull try catch ifnull if );      }  

     

       Action上下文创建(重点)

     

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

    Java代码  收藏代码
    1. static new  Map<String, Object> context;  
    [java] view plaincopy
     
    1. staticnew Map<String, Object> context;  

     
       下面我们看下如何创建action上下文的,代码如下:

     

    Java代码  收藏代码
    1. /**  
    2. *创建Action上下文,初始化thread local  
    3. */  public ;  
    4. if null  ;  
    5.   
    6. if null    
    7. new new  else  class null   
    8. new    
    9. return  }  
    [java] view plaincopy
     
    1. /** 
    2. *创建Action上下文,初始化thread local 
    3. */ public ;  
    4. ifnull ;  
    5.   
    6. ifnull   
    7. newnew else class null   
    8. new   
    9. return }  

     

        上面代码中dispatcher.createContextMap,如何封装相关参数:

     

    Java代码  收藏代码
    1. public   
    2. new    
    3. new    
    4. new    
    5. new    
    6. if null  return  }  
    [java] view plaincopy
     
    1. public   
    2. new   
    3. new   
    4. new   
    5. new   
    6. ifnull return }  

     

     我们简单看下RequestMap,其他的省略。RequestMap类实现了抽象Map,故其本身是一个Map,主要方法实现:

    Java代码  收藏代码
    1. //map的get实现  public  return  //map的put实现  public  null  return  }  
    [java] view plaincopy
     
    1. //map的get实现 public return //map的put实现 public null return }  

     

       下面是源码展示了如何执行Action控制器:

     

    Java代码  收藏代码
    1. public voidthrows  public void throws    
    2.   
    3. boolean null  if  if null  if null    try    
    4.   
    5.   
    6.   
    7. class true false    
    8.   
    9. if null  else    
    10. if  catch    
    11. if  if null   + request.getQueryString();  
    12.   else    catch  finally      }  
    [java] view plaincopy
     
    1. publicvoidthrows publicvoid throws   
    2.   
    3. booleannull if ifnull ifnull try   
    4.   
    5.   
    6.   
    7. class truefalse   
    8.   
    9. ifnull else   
    10. if catch   
    11. if ifnull  + request.getQueryString();  
    12. else catch finally     }  

     

       文中对如何解析Struts.xml,如何将URL与action映射匹配为分析,有需要的我后续补全,因为 StrutsXmlConfigurationProvider继承XmlConfigurationProvider,并在register方法回调父 类的register,有兴趣的可以深入阅读下下XmlConfigurationProvider源码:

     

    Java代码  收藏代码
    1. public void throws  if null class class new  public throws  return    
    2. super     }  
    [java] view plaincopy
     
    1. publicvoidthrows ifnullclass classnew publicthrows return   
    2. super    }  

     

     

         struts2-core-2.2.1.jar包中struts-2.1.7.dtd对于Action的定义如下:

    Xml代码  收藏代码
    1. <!ELEMENT action (param|result|interceptor-ref|exception-mapping)*    
    [xml] view plaincopy
     
    1. <!ELEMENT action (param|result|interceptor-ref|exception-mapping)*> >  

        从上述DTD中可见Action元素可以含有name 、class 、method 、converter 属性。

     

       XmlConfigurationProvider解析struts.xml配置的Action元素:

    Java代码  收藏代码
    1. protected void throws  );  
    2. );  
    3. );  
    4. if null      
    5. ) ? methodName.trim() :  null    
    6.   
    7. if    
    8.              className = packageContext.getDefaultClassRef();  
    9.          } else {  
    10.              className = ActionSupport.class.getName();  
    11.          }*/  else  if  if  return  try  catch  throw new   new if  ) :  ) + name +     }  
    [java] view plaincopy
     
    1. protectedvoidthrows );  
    2. );  
    3. );  
    4. ifnull   
    5. ) ? methodName.trim() : null   
    6.   
    7. if   
    8.              className = packageContext.getDefaultClassRef(); 
    9.          } else { 
    10.              className = ActionSupport.class.getName(); 
    11.          }*/ else if if return try catch thrownew new if ) : ) + name +   }  

     

  • 相关阅读:
    IndexedDB demo showcase
    javascript for
    IndexedDB
    web sql Database
    webSql
    哈哈 代表月亮
    网易
    Android 百度地图 SDK v3.0.0 (一)
    iOS使用Instrument的Leaks查找代码内存泄露
    换主页轮播的主题图片(4、删除)---轻开电子商务系统(企业入门级B2C站点)
  • 原文地址:https://www.cnblogs.com/splin/p/4270651.html
Copyright © 2020-2023  润新知