ActionServlet详解

大家都知道,Struts控制器组件负责接受用户请求,更通模型,以及返回给用户合适的视图组件. 
控制器将模型层和视图层分开,这样分离,可以为同一个模型开发出不同的视图. 
下面时Struts的三大主要组件 
ActionServlet组件:充当Struts框架的中央控制器 
RequestProcessor组件:充当每个子应用模块的请求处理器 
Action组件:真正来处理一项具体的业务. 

一. Struts的init()方法  
Struts应用中只存在ActionServlet的一个实例,Servlet容器在启动时,或者用户首次请求ActionServlet时加载ActionServlet类.在这两种情况下,servlet容器都会在ActionServlet容器被加载后立即执行它的init()方法,这可以保证ActionServlet处理用户请求时已经被初始化. 

下面根据Init()讲述Struts的初始化过程 
Java代码   收藏代码
  1. public void init() throws ServletException {  
  2.   
  3.         // Wraps the entire initialization in a try/catch to better handle  
  4.         // unexpected exceptions and errors to provide better feedback  
  5.         // to the developer  
  6.         try {  
  7. //调用initInternal()方法,初始化Struts框架内的消息资源,如与系统日志相关的通知,警告,和错误消息.  
  8. 1)initInternal();  
  9.   
  10. //调用ininOther()方法,从web.xml文件中加载ActionServlet的初始化参数,如config参数  
  11. 2)initOther();  
  12.   
  13. //调用initServlet()方法,从web.xml文件中加载ActionServlet的URL映射信息.同时还会注册web.xml文件和Struts配置文件所使用的DTD文件,这些DTD文件用户验证web.xml和struts配置文件的语法.其中方法里的 digester类负责解析web.xml,对字符串servletMapping属性进行初始化  
  14. 3) initServlet();  
  15.   
  16. //把ActionServlet实例放到ServletContext里  
  17. getServletContext().setAttribute(Globals.ACTION_SERVLET_KEY, this);  
  18.   
  19. //初始化一个factory,用于创建moduleConfig  
  20. initModuleConfigFactory();  
  21.   
  22. //,加载并解析默认struts配置文件/WEB-INF/struts-config.xml,同时创建MoudleConfig实例,放到ServletContext中  
  23. 4)ModuleConfig moduleConfig = initModuleConfig("", config);  
  24.   
  25. //加载并初始化默认子应用模块的消息资源;讲解MessageResources对象,把它存储在ServletContext中.  
  26. 5)initModuleMessageResources(moduleConfig);  
  27.   
  28. //加载并初始化默认子应用模块的数据源,如果在struts配置文件中没有定义元素,忽略这一流程.  
  29. 6)initModuleDataSources(moduleConfig);  
  30.   
  31. //加载并初始化默认子应用的所有插件  
  32. 7)initModulePlugIns(moduleConfig);  
  33.   
  34. //冻结moduleConfig(,在方法返回之前不能修改它,否则将抛出异常)  
  35. moduleConfig.freeze();  
  36.           
  37. //如果还有其他子应用模块,将重复4-7步  
  38.       Enumeration names = getServletConfig().getInitParameterNames();  
  39.             while (names.hasMoreElements()) {  
  40.                 String name = (String) names.nextElement();  
  41.                 if (!name.startsWith("config/")) {  
  42.                     continue;  
  43.                 }  
  44.                 String prefix = name.substring(6);  
  45.                 moduleConfig = initModuleConfig  
  46.                     (prefix, getServletConfig().getInitParameter(name));  
  47.                 initModuleMessageResources(moduleConfig);  
  48.                 initModuleDataSources(moduleConfig);  
  49.                 initModulePlugIns(moduleConfig);  
  50.                 moduleConfig.freeze();  
  51.      }  
  52.   
  53. //将各个子模块应用(除了默认的)的前缀存到一个字符数组中,并放到servletcontext中  
  54. this.initModulePrefixes(this.getServletContext());  
  55. //释放创建的用于读取配置文件的digester实例,释放内存  
  56.             this.destroyConfigDigester();  
  57.         } catch (UnavailableException ex) {  
  58.             throw ex;  
  59.         } catch (Throwable t) {  
  60.             // The follow error message is not retrieved from internal message  
  61.             // resources as they may not have been able to have been   
  62.             // initialized  
  63.             log.error("Unable to initialize Struts ActionServlet due to an "  
  64.                 + "unexpected exception or error thrown, so marking the "  
  65.                 + "servlet as unavailable.  Most likely, this is due to an "  
  66.                 + "incorrect or missing library dependency.", t);  
  67.             throw new UnavailableException(t.getMessage());  
  68.         }      
  69. }  


     将各个子模块应用(除了默认的)的前缀存到一个字符数组中,并放到servletcontext中,对于默认的子应用模块,在appclication范围内存放他的MoudleConfig实例的key为“org.apache.struts.action.MODULE”,其他模块如/account,存放的key为org.apache.struts.action.MODULE/account,消息,数据源和插件等部分存在servletcontext的key和上述方法类似,不在说明. 


二.ActionServlet的process方法  
当ActionServlet接受到HTTP请求后,在doget()或doPost()方法中都会调用process()方法来处理请求. 
Java代码   收藏代码
  1.  public void doGet(HttpServletRequest request,  
  2.               HttpServletResponse response)  
  3.         throws IOException, ServletException {  
  4.   
  5.         process(request, response);  
  6.   
  7. }   

Java代码   收藏代码
  1.     public void doPost(HttpServletRequest request,  
  2.                HttpServletResponse response)  
  3.         throws IOException, ServletException {  
  4.   
  5.         process(request, response);  
  6.   
  7. }   

下面是process方法,它看上去并不复杂,但他调用的其他方法比较复杂. 
Java代码   收藏代码
  1.   protected void process(HttpServletRequest request, HttpServletResponse response)  
  2.         throws IOException, ServletException {  
  3.         //根据request里的信息从servletContext里找到相应的子模块ModuleConfig,和它下面的MessageResources,并放到request里,使其他组件可以方便的供request里取得应用配置信息和消息资源.  
  4.         ModuleUtils.getInstance().selectModule(request, getServletContext());  
  5. //取出MoudleConfig实例config  
  6.         ModuleConfig config = getModuleConfig(request);  
  7.     //根据config里这个子模块的信息,从servletcontext里,取出这个子模块的RequestProcessor实例  
  8.         RequestProcessor processor = getProcessorForModule(config);  
  9.     //如果processor实例为空,就新建一个.同时放到servletcontext里.  
  10.         if (processor == null) {  
  11.            processor = getRequestProcessor(config);  
  12.         }  
  13. //调用RequestProcessor的process方法处理,  
  14.         processor.process(request, response);  
  15.     }  


三. 扩展ActionServlet类
 
从Struts1.1开始,为减轻ActionServlet的负担,多数功能已经移到RequestProcessor类中,所以基本不用扩展ActionServlet类  

如果需要创建自己的ActionServlet,则可以创建一个它的子类.覆盖init()方法(或其他方法),可以写一些自己的操作,但要先调用super.init(); 
定义如下的类: 
Java代码   收藏代码
  1. package sample;   
  2. public class ExtendedActionServlet extends ActionServlet {   
  3.         public void init() throws ServletException {   
  4.                super.init();   
  5.                //do some operations   
  6.                ……………   
  7.         }   
  8. }   

扩展完类后,还应该在web.xml文件中如下配置: 
Java代码   收藏代码
  1.    
  2.         sample   
  3.         class>sample.ExtendedActionServletclass>   
  4.    
  5.    
  6.    
  7.        sample   
  8.        /action/*   

上面的/action/*表示负责处理所有以/action为前缀的URL,后面的/表示转义 

你可能感兴趣的:(Java)