首页 > 代码库 > Struts——三大组件(二)RequestProcessor

Struts——三大组件(二)RequestProcessor

RequestProcessor

       

         ActionServlet是Struts框架里唯一一个Servlet,它负责处理所有请求。它无论何时收到一个请求,都会首先试着为现有请求找到一个子应用。一旦子应用被找到,它会为其生成一个RequestProcessor对象,并调用传入HttpServletRequest和HttpServletResponse为参数的process()方法。

 

一、RequestProcessor.process()

java代码:

public void process(HttpServletRequest request, HttpServletResponse response)
			throws IOException, ServletException {
		//如果HttpServletRequest是POST方式,且请求为multipart/form-data 
		//Struts框架将请求对象包装成处理multipart 请求专用的请求对象,否则,只是简单地返回原有的请求对象
		request = processMultipart(request);
		//该方法用来从请求URI中获应用取路径部分。获取到的信息在稍后的步骤中用于选择合适的Struts Action调用。
		String path = processPath(request, response);
		if (path == null) {
			return;
		}
		if (log.isDebugEnabled()) {
			log.debug("Processing a '" + request.getMethod() + "' for path '"
					+ path + "'");
		}
		//处理一些国际化的事务
		processLocale(request, response);
		//来决定请求的content type编码(encoding)方式
		processContent(request, response);
		//根据noCache属性的设置调用processNoCache() 方法,
		//如果noCache设置为true。则添加合适的响应头到响应对象中,使得页面保留在浏览器的Cache中
		processNoCache(request, response);
		// General purpose preprocessing hook
		//这个方法在这儿设置一个钩子,方法的默认实现只是简单地返回true,
		//这样给了自定义处理器的开发者提供了一个合适的地方让你添加自己的业务逻辑。
		//因为这个方法在调用Action之前被调用,如果你重载这个方法,只需要返回false,则Action就不会被调用
		if (!processPreprocess(request, response)) {
			return;
		}
		this.processCachedMessages(request, response);
		// Identify the mapping for this request
		//根据客户请求信息中的path信息来决定是否返回ActionMapping对象实例。
		//如果不能够找到path 的映射,则客户将会得到一个error 响应。 
		ActionMapping mapping = processMapping(request, response, path);
		if (mapping == null) {
			return;
		}
		// Check for any role required to perform this action
		//检查是否为Action配置了安全角色。
		//如果配置了角色要求,则请求对象的isUserInRole()方法被调用,
		//如果用户属于这些角色,则客户会得到显示一个error 响应。 
		if (!processRoles(request, response, mapping)) {
			return;
		}
		// Process any ActionForm bean related to this request
		//检查是否存在为ActionMapping配置的ActionForm 。
		//如果存在,则在有效区域内查找是否存在该ActionForm 的实例,存在,则复用,不存在,则创建一个实例。
		//然后将实例保存与再配置文件中配置好的有效区域(request,session,application)内,
		//并用Action元素的name属性作为该实例的关键字。 
		ActionForm form = processActionForm(request, response, mapping);
		//如果存在为ActionMapping配置的ActionForm,
		//则封装请求对象中的数据到ActionForm 中,
		//在进行封装之前,先调用ActionForm 的reset()方法进行属性值的默认化。 
		processPopulate(request, response, form, mapping);
		// Validate any fields of the ActionForm bean, if applicable
		//如果ActionForm被配置好,并且action元素的属性validate被设置为true ,
		//则进一步调用validate()方法进行规则校验。
		//如果validate()方法校验失败,就会保存一个ActionErrors 对象到请求区域中,
		//请求将会自动重定向到action映射的input属性所指定的页面中。
		//如果校验通过或在action 映射中没有配置ActionForm,则继续处理请求。 
		try {
			if (!processValidate(request, response, form, mapping)) {
				return;
			}
		} catch (InvalidCancelException e) {
			ActionForward forward = processException(request, response, e,
					form, mapping);
			processForwardConfig(request, response, forward);
			return;
		} catch (IOException e) {
			throw e;
		} catch (ServletException e) {
			throw e;
		}
		//根据action 映射是否配置了forward属性或include属性来决定下一步操作。
		//如果配置了任意一个,则相应地调用RequestDispatcher对象的forward()方法或include()方法,
		//调用后,对客户请求的处理结束。否则,继续处理请求。 
		// Process a forward or include specified by this mapping
		if (!processForward(request, response, mapping)) {
			return;
		}
		if (!processInclude(request, response, mapping)) {
			return;
		}
		//创建或获取一个Action对象实例处理请求。
		//processActionCreate()方法会在缓存中查找是否存在已经创建好的Action实例,
		//如果存在,则复用,否则,则重新创建并将其村于缓存中。 
		Action action = processActionCreate(request, response, mapping);
		if (action == null) {
			return;
		}
		// Call the Action instance itself
		//该方法用于在一个try/catch 代码块中调用action 实例的execute()方法,
		//这样确保action 的execute()方法一旦发生执行异常能够被RequestProcessor捕获。 
		ActionForward forward = processActionPerform(request, response, action,
				form, mapping);
		// Process the returned ActionForward instance
		//通过检查ActionForward对象实例,决定采用redirect或forword方式进行重定向。究竟采用redirect还是 
		//forword取决于forward元素的redirect属性值。
		processForwardConfig(request, response, forward);
	
		
	}



二、扩展RequestProcessor

       如果想修改RequestProcessor的一些默认功能,改易覆盖RequestProcessor基类中的相关方法.

Java代码

Public classCustomRequestProcessor extends RequestProcessor{  
  protected void processPreprocess(HttpServletRequest request,  
                                 HttpServletResponse response) {  
 
request.setCharacterEncoding("UTF-8");  //在这加一行设置编码的的代吗。
 super.process(request, response);
}  
} 


 

在struts配置文件中,<controller>元素的processorClass属性用于配置你自己的RequestProcessor类

<controller  
contentType=“text/html:charset=”GB2312”  
locale=”true”nocache=”true” processorCalss=”com.test.CustomRequestProcessor”/> 


 

总结

          大部分请处理都是在RequestProcessor.process()发生的。Process()方法是以模板方法(TemplateMethod)的设计模式来实现的,其中有完成request处理的每个步骤的方法;所有这些方法都从process()方法顺序调用。例如,寻找当前请求的ActionForm类和检查当前用户是否有权限执行actionmapping都有几个单独的方法。这给我们提供了极大的弹性空间。Struts的RequestProcessor对每个请求处理步骤都提供了默认的实现方法。这样就可以重写需要的方法,而其余剩下的保留默认实现。