ActionServlet类是Struts框架的内置核心控制器组件,它继承了javax.servlet.http.HttpServlet类,Struts的启动一般从加载ActionServlet开始,因此它在MVC模型中扮演中央控制器的角色,负责接受用户请求,返回给用户合适的视图组件.控制器将模型层和视图层分开,这样分离,可以为同一个模型开发出不同的视图.
下面是Struts的三大主要组件:
ActionServlet组件:充当Struts框架的中央控制器;Struts应用中只存在ActionServlet的一个实例。
RequestProcessor组件:充当每个子应用模块的请求处理器。
Action组件:真正来处理一项具体的业务.。
ActionServlet
Servlet容器在启动时,或者用户首次请求ActionServlet时加载ActionServlet类.在这两种情况下,servlet容器都会在ActionServlet容器被加载后立即执行它的init()方法,这可以保证ActionServlet处理用户请求时已经被初始化.
Java代码——init()
public void init() throws ServletException { final String configPrefix = "config/"; final int configPrefixLength = configPrefix.length() - 1; try { // 调用initInternal()方法,初始化Struts框架内的消息资源,如与系统日志相关的通知,警告,和错误消息. initInternal(); // 调用ininOther()方法,从web.xml文件中加载ActionServlet的初始化参数,如config参数 initOther(); // 调用initServlet()方法,从web.xml文件中加载ActionServlet的URL映射信息. // 同时还会注册web.xml文件和Struts配置文件所使用的DTD文件, // 这些DTD文件用户验证web.xml和struts配置文件的语法.其中方法里的 digester类负责解析web.xml, // 对字符串servletMapping属性进行初始化 initServlet(); initChain(); // 把ActionServlet实例放到ServletContext里 getServletContext().setAttribute(Globals.ACTION_SERVLET_KEY, this); // 初始化一个factory,用于创建moduleConfig initModuleConfigFactory(); // 加载并解析默认struts配置文件/WEB-INF/struts-config.xml,同时创建MoudleConfig实例,放到ServletContext中 ModuleConfig moduleConfig = initModuleConfig("", config); // 加载并初始化默认子应用模块的消息资源;讲解MessageResources对象,把它存储在ServletContext中. initModuleMessageResources(moduleConfig); // 加载并初始化默认子应用的所有插件 initModulePlugIns(moduleConfig); initModuleFormBeans(moduleConfig); initModuleForwards(moduleConfig); initModuleExceptionConfigs(moduleConfig); initModuleActions(moduleConfig); // 冻结moduleConfig(在方法返回之前不能修改它,否则将抛出异常) moduleConfig.freeze(); Enumeration names = getServletConfig().getInitParameterNames(); while (names.hasMoreElements()) { String name = (String) names.nextElement(); if (!name.startsWith(configPrefix)) { continue; } String prefix = name.substring(configPrefixLength); moduleConfig = initModuleConfig(prefix, getServletConfig() .getInitParameter(name)); initModuleMessageResources(moduleConfig); initModulePlugIns(moduleConfig); initModuleFormBeans(moduleConfig); initModuleForwards(moduleConfig); initModuleExceptionConfigs(moduleConfig); initModuleActions(moduleConfig); moduleConfig.freeze(); } // 将各个子模块应用(除了默认的)的前缀存到一个字符数组中,并放到servletcontext中 this.initModulePrefixes(this.getServletContext()); // 释放创建的用于读取配置文件的digester实例,释放内存 this.destroyConfigDigester(); } catch (UnavailableException ex) { throw ex; } catch (Throwable t) { // The follow error message is not retrieved from internal message // resources as they may not have been able to have been // initialized log.error( "Unable to initialize Struts ActionServlet due to an " + "unexpected exception or error thrown, so marking the " + "servlet as unavailable. Most likely, this is due to an " + "incorrect or missing library dependency.", t); throw new UnavailableException(t.getMessage()); } }
—————————————————————————————————————————————————
当ActionServlet接受到HTTP请求后,在doget()或doPost()方法中都会调用process()方法来处理请求.
Java代码——process()
protected void process(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { // 根据request里的信息从servletContext里找到相应的子模块ModuleConfig, // 和它下面的MessageResources,并放到request里,使其他组件可以方便的供request里取得应用配置信息和消息资源. ModuleUtils.getInstance().selectModule(request, getServletContext()); // 取出MoudleConfig实例config ModuleConfig config = getModuleConfig(request); // 根据config里这个子模块的信息,从servletcontext里,取出这个子模块的RequestProcessor实例 RequestProcessor processor = getProcessorForModule(config); // 如果processor实例为空,就新建一个.同时放到servletcontext里. if (processor == null) { processor = getRequestProcessor(config); } // 调用RequestProcessor的process方法处理, processor.process(request, response); }
ActionServlet.process()看起来不复杂,但是他调用的RequestProcessor.process()方法比较复杂(下篇博客会介绍)。
扩展ActionServlet类
从Struts1.1开始,为减轻ActionServlet的负担,多数功能已经移到RequestProcessor类中,所以基本不用扩展ActionServlet类。
如果需要创建自己的ActionServlet,则可以创建一个它的子类.覆盖init()方法(或其他方法),可以写一些自己的操作,但要先调用super.init();
定义如下的类:
package sample; public classExtendedActionServlet extends ActionServlet { public void init() throwsServletException { super.init(); //do some operations …………… } }
扩展完类后,还应该在web.xml文件中如下配置:
<servlet> <servlet-name>sample</servlet-name> <servlet-class>sample.ExtendedActionServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>sample</servlet-name> <url-pattern>/action/*<url-pattern>
上面的/action/*表示负责处理所有以/action为前缀的URL,后面的/表示转义
总结
Web服务器接到Request请求时,首先加载并初始化ActionServlet。ActionServlet会读取struts-config.xml配置文件,把配置文件信息存入ActionMapping对象中供以后使用。在Struts中,它的主要作用是用来接收用户的请求信息,然后根据系统配置要求将请求传递给相应的Action对象。ActionServlet并不是真正干活的类,真正干活的是RequestDispatcher和Action。
Struts——三大组件(一)ActionServlet