首页 > 代码库 > Struts——三大组件(一)ActionServlet

Struts——三大组件(一)ActionServlet

          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并不是真正干活的类,真正干活的是RequestDispatcherAction