`
hain
  • 浏览: 448978 次
  • 来自: ...
社区版块
存档分类
最新评论

RequestProcessor

阅读更多
 

RequestProcessor及其在struts-config.xml中的配置

<controller processorClass="cn.ourbooks.common.MyRequestProcessor" />

通常来讲,好象不常用到。

但如果想从源头抓头对Web层的控制,就非得做一个RequestProcessor的过滤器。

 

在这里说一个最明显示的例子:

在使用Struts的过程中,对Session Timeout或者客户是否登录的判断往往是放到一个Action基类(继承于StrutsAction)中处理(反正以前我们的系统就是这样的),放到Action基类里的意图很明显是不需要在jsp或每个小处理的Action中处理这种共性的事务。

但是在测试过程中发现,StrutsFormvalidate在验证出错后,不会走Action而是直接mapping到错误页面了。这样,我们的Session Timeout的判断机制就不管用了。

这种情况下有时会给客户一个很不友好的感觉。客户输入了很多数据,提示有错(这时有可能已经Session Timeout,但系统没有觉查),改完了,再提交,如果验证通过,此时有可能会告诉客户,您没有登录或是Session Timeout。对于客户来讲大有捶胸顿足的气愤,要提示Session Timeout早提示,偏偏三番五次改正确了,却又提示Session Timeout

 

此时怎么办呢?

Struts在诸类框架中的老大地位,决定了其非常强的扩展功能。

我们可以配置自己的RequestProcessor,比如MyRequestProcessor

重置其中的processValidate方法,在调用父类的processValidate方法之前进行Session Timeout的验证,如果验证不过,就可以转移到公共Session Timeout的页面了,否则,就可以调用父类的processValidate方法。

写完MyRequestProcessor类后,还需要在struts-config.xml中配置一下,格式如下:

<controller processorClass="cn.ourbooks.common.MyRequestProcessor" />

这样,在调用ActionFormvalidate方法之前就进行了Session Timeout的验证,使系统对Session Timeout作到有效的把握。

 

以上只是例一,再谈个例二,例二是个补救的例子。

StrutsRequestProcessor中会维护一个action Map,里面放着用过的Action,在一个请求来了之后,先判断这个请求的actionaction Map中是否存在,如果不存在就创建一个,并加到action Map中,如果已经存在,就不创建新的了,取出来用就是了。

默认情况下,TomcatAP Searver)中也只是维护着一个Action Servlet,这一连串下来,有一个很关键的问题,我们需要注意,就是在Action中不能声明属性,如果声明了,这个属性是所有请求共享的。举例说明就是,假如在Action中声明了属性,并定义其默认值为123,第一个访问者(请求)将这个属性的值改为了abc,那么第二个访问者(请求)取得这个属性的值时,将得到abc,而不是123

哈哈,如果有个很糟糕的情况,你的系统已经做的很大了,而且在Action中也定了好多属性,怎么办呢?难道改造所有的Action,那代价太大了。

好了,还是RequestProcessor,我们可以在其子类MyRequestProcessor(也就是上例我们自己做的那个)中,重置processActionCreate方法,大家可以查一下Struts关于RequestProcessor类的源码,找到processActionCreate方法,原封不动拷到MyRequestProcessor中,注释下面几行:

            instance = (Action) actions.get(className);

            if (instance != null) {

                if (log.isTraceEnabled()) {

                    log.trace("  Returning existing Action instance");

                }

                return (instance);

            }

就实现了每个请求,都创建一个新的Action实例。这样,即使在Action中声明了属性,在多请求的情况下,也互不影响(虽然效率上可能低点,但是总比项目快结束了,再返工的好)。

Struts框架只允许应用中存在一个ActionServlet类,但是可以存在多个客户化的RequestProcessor类,每个子应用模块都可以拥有单独的RequestProcessor类,如果像修改RequestProcessor类的一些默认功能,可以覆盖RequestProcessor基类中的相关方法。

 

 

 

下面我们来介绍其中的process()方法:

  /**
  * <p>
  * Process an <code>HttpServletRequest</code> and create the corresponding
  * <code>HttpServletResponse</code>.
  * </p>
  *
  * @param request
  *            The servlet request we are processing
  * @param response
  *            The servlet response we are creating
  *
  * @exception IOException
  *                if an input/output error occurs
  * @exception ServletException
  *                if a processing exception occurs
  */
 public void process(HttpServletRequest request, HttpServletResponse response)
   throws IOException, ServletException {

 

其执行流程如下:

 

 

 

(1)                调用processMultipart()方法,如果HTTP请求方式为POST,并且请求的coutentType属性以”Multipart/form-data”开头,标准的HttpServletRequest对象将被重新包装,以方便处理“Multipart”类型的HTTP请求,如果请求方式为GET,或者contentType属性不是“multipart”,就直接返回原始的HttpServletRequest对象。

 

 

 

(2)                调用processPath(),获得请求URI路径,这一信息可用于选择合适的Struts Action组件。

 

 

 

(3)                调用processLocale()方法,当ControllerConfig对象的locale属性为true,将读取用户请求中包含的Locale信息,然后把Locale实例保存在session范围内。

 

 

 

(4)                 调用processContent(),读取ControllerConfig对象的contentType属性,然后调用response.setContentType(content Type)方法,设置响应结果的文档类型和字符编码。processContent()方法的代码如下:

 

 

 

protected void processContent(HttpServletRequest request,HttpServletResponse){

 

 

 

        String contentType=moduleConfig.getControllerConfig().getContentType();

 

 

 

If(contentType!=null) {

 

 

 

        Response.setContentType(contentType);

 

 

 

     }

 

 

 

}

 

 

 

(5)                调用processNoCache(),读取ControllerConfig对象的nocache属性,如果nocache属性为true,在响应结果中将加入特定的头参数:Pragma,Cache-Control和Expires,防止页面被存储在客户浏览器的缓存中,processNoCache()方法的代码如下:

 

 

 

protected void processNoCache(HttpServletRequest request,HttpServletResponse response){

 

 

 

     if(moduleConfig.getControllerConfig().getNoCache()) {

 

 

 

          response.setHeader(“Pragma”,”NoCache”);

 

 

 

          response.setHeader(“Cache-Control”,”no-cache”);

 

 

 

          response.setHeader(“Expires”,1);

 

 

 

        }

 

 

 

}

 

 

 

(6)                调用processPreprocess(),该方法不执行任何操作,直接返回true,子类可以覆盖这个方法,执行客户化的预处理请求操作。

 

 

 

(7)                调用processMapping(),寻找和用户请求的URI匹配的ActionMapping,如果不存在这样的ActionMapping,则向用户返回恰当的错误信息。

 

 

 

(8)                调用processRoles(),现判断是否为Action配置了安全角色,如果配置了安全角色,叫调用isUserInRole()方法判断当前用户是否具备必须的角色。如果不具备,就结束请求处理流程,向用户返回恰当的错误信息。

 

 

 

(9)                调用processActionForm(),现判断是否为ActionMapping配置了ActionForm,如果配置了ActionForm(),就先从ActionForm的存在范围内寻找该ActionForm的实例,如果不存在,就创建一个实例,接下来把它保存在合适的范围内,保存时使用的属性key为ActionForm的name属性。

 

 

 

(10)            调用processPopulate()方法,如果为ActionMapping配置了ActionForm,就先调用ActonForm的reset()方法,再把请求中的表单数据组装到ActionFrom中。

 

 

 

(11)            调用processValidate(),如果为ActionMapping 配置了ActionForm,并且ActionMapping 的validate属性为true,就调用ActionForm的validate()方法,如果validate()方法返回的ActionErrors对象中包含ActionMessage对象,说明表单验证失败,就把ActionErrors对象存储在request范围内,再把请求转发到ActionMapping的input属性指定的WEB组件,如果ActionForm的valildate()方法执行表单验证成功,就继续执行下一个请求处理流程。

 

 

 

(12)            调用processForward(),判断是否在ActionMapping中配置了forward属性,如果配置了这个属性,就调用RequestDispatcher的forward()方法,请求处理流程结束,否则进行下一步。

 

 

 

(13)            调用processInclude(),判断是否在ActionMapping中配置了include属性,如果配置了这个属性,就调用RequestDispatcher的include()方法,请求处理流程结束,否则进行下一步。

 

 

 

(14)            调用processActionCreate()方法,现判断是否在Action缓存中存在这个Action实例,如果不存在,就创建一个实例,把它保存在Action缓存中。

 

 

 

(15)            调用processActionPerform()方法,该方法再调用Action实例的execute()方法,execute()方法位于try/catch代码中,以便捕获异常。代码如下:

 

 

 

protected ActionForward processActionPerform(HttpServletRequest request,HttpServletResponse response,Action action, ActionMapping mapping)throws IOException,ServletException{

 

 

 

   try{

 

 

 

         return(action.execute(mapping,form,request,response));

 

 

 

       }catch(Exception e){

 

 

 

         return(processException(request,response,e,form,mapping));

 

 

 

       }

 

 

 

}

 

 

 

(16)            调用processActionForward()方法,把Action 的execute()方法返回的ActionForward对象作为参数来传给它。processActionForward()根据ActionFroward对象包含的请求转发信息来执行请求转发或重定向。

 

 

 

注意:在struts中,ControllerConfig类与配置文件中的<controller>元素对应,ActionMapping类和<action>元素对应,ActionForward类和<forward>元素对应

 

 

 

扩展RequestProcessor类

 

 

 

下面我们来实现用户在同一个会话的任何时候都可以改变它的Locale设置,在RequestProcessor类中定义的processLocale()方法的默认行为是: 仅仅当session范围呢不存在Locale实例的时候,才会把Locale实例保存在session内,这通发生在处理同一个对话的第一个请求时。

 

 

 

那么我们怎样实现在同一个会话的任何时候都可以改变它的Locale设置呢?我们扩展RequestProcessor类,检查每次用户发出的HTTP请求中包含的Locale信息,每当Locale发生变化时,就会把新的Locale实例保存在session范围内。

 

 

 

代码如下:

 

 

 

package sample;
import javax.servlet.http*;

 

 

 

import java.util.Locale;

 

 

 

import org.apache.struts.action.Action;

 

 

 

import org.apache.struts.action.RequestProcessor;

 

 

 

import org.apache.struts.action.Globals;

 

 

 

 

 

 

public class ExtendedRequestProcessor extends RequestProcessor{

 

 

 

      protected void processLocale(HttpServletRequest request,HttpServletResponse response){

 

 

 

        if(!moduleConfig.getControllerConfig().getLocale()){

 

 

 

           return

 

 

 

               }//end if

 

 

 

//get the locale that stored in the user’s session if any

 

 

 

        HttpSession session=request.getSession();

 

 

 

        Locale sessionLocale=(Locale)session.getAttribute(Globals.LOCALE_KEY);

 

 

 

        }

 

 

 

//get the user’s preferred Locale form the request

 

 

 

       Locale requestLocale=request.getLocale();

 

 

 

 

 

 

//if was never a locale in the session or it has changed ,set it

 

 

 

if(sessionLocale==null||(sessionLocale!=requestLocale)){

 

 

 

           if(log.isDebugEnabled()) {

 

 

 

分享到:
评论
2 楼 e_soft 2009-03-29  
注释掉

instance = (Action) actions.get(className);

            if (instance != null) {

                if (log.isTraceEnabled()) {

                    log.trace("  Returning existing Action instance");

                }

                return (instance);

            }

会有其他问题。
我一个同学做的系统Action要保留东西的,连续要处理好几个request
你把它注释掉了就每次生成一个新的Action,不好使
1 楼 e_soft 2009-03-29  
注释掉

instance = (Action) actions.get(className);

            if (instance != null) {

                if (log.isTraceEnabled()) {

                    log.trace("  Returning existing Action instance");

                }

                return (instance);

            }

会有其他问题。
我一个同学做的系统Action要保留东西的,连续要处理好几个request
你把它注释掉了就每次生成一个新的Action,不好使

相关推荐

    DisapatchAction测试和RequestProcessor控制器类

    DisapatchAction测试和RequestProcessor控制器类

    struts1整合spring 通过代理RequestProcessor实现

    这只是一个最简单的demo,只有一个action, 通过代理RequestProcessor实现

    commons-beanutils-1.7.0

    at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:431) at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:236) at org.apache.struts....

    struts1流程和原理

    2、RequestProcessor类(处理异常的核心组件)。 3、ActionForm(接收页面中传过的数据)。 4、Action(是控制器,主要是从ActionForm中接收页面传进来的数据,然后进行逻辑 处理)。 5、ActionForward(页面跳转,...

    StrutsAPI(java)

    在請求來臨後,RequestProcessor 根據請求URI呼叫對應的Action物件,將工作交給它,並在最後由Action物件得到一個ActionForward物件, ActionServlet使用ActionForward得知將流程forward至指定的資源。 當請求到達...

    JSP Struts配置文件详解

    默认org.apache.struts.action.RequestProcessor @tempDir:指定文件上传时的临时工作目录.如果没有设置,将才用Servlet容器为web应用分配的临时工作目录. @nochache:true时,在相应结果中加入特定的头参数:Pragma ,...

    精通Struts基于MVC的Java Web设计与开发 孙卫琴 光盘

    第4章到第7章深入探讨了Struts框架的核心组件ActionServlet和RequestProcessor的实现原理,详细介绍了开发Struts应用的模型、视图和控制器的各种技术,细致的描述了Struts配置文件的每个元素的使用方法。第8章到第9...

    jsp应用开发源代码

    流程控制层 通过一个特定的请求处理器JAVA类:RequestProcessor.java,将客户端的请求(如:http://localhost:6888/myshop/shp/cart 转化成某个事件(如:CartEvent、OrderEvent...),并交给控制器类...

    精通 Struts:基于 MVC 的 JavaWeb 设计与开发(PDF)

    第4章到第7章深入探讨了Struts框架的核心组件ActionServlet和RequestProcessor的实现原理,详细介绍了开发Struts应用的模型、视图和控制器的各种技术,细致的描述了Struts配置文件的每个元素的使用方法。第8章到第9...

    JSP应用开发源代码

    N-Tier式的分布式应用 表示层 JSP、HTML、DHTML、XML/XSL、JAVA BEAN、TAGLIB 流程控制层 通过一个特定的请求处理器JAVA类:RequestProcessor.java,将客户端的请求(如:http://localhost:6888/myshop/shp/cart 转化...

    基于MVC的java Web设计与开发

    第4章到第7章深入探讨了Struts框架的核心组件ActionServlet和RequestProcessor的实现原理,详细介绍了开发Struts应用的模型、视图和控制器的各种技术,细致的描述了Struts配置文件的每个元素的使用方法。第8章到第9...

    精通Struts_基于MVC的Java Web设计与开发

    第4章到第7章深入探讨了Struts框架的核心组件ActionServlet和RequestProcessor的实现原理,详细介绍了开发Struts应用的模型、视图和控制器的各种技术,细致的描述了Struts配置文件的每个元素的使用方法。第8章到第9...

    精通struts:基于mvc的java web设计与开发part3

    第4章到第7章深入探讨了Struts框架的核心组件ActionServlet和 RequestProcessor的实现原理,详细介绍了开发Struts应用的模型、视图和控制器的各种技术,细致的描述了Struts配置文件的每个元素的使用方法。...

    精通struts:基于mvc的java web设计与开发part2

    第4章到第7章深入探讨了Struts框架的核心组件ActionServlet和 RequestProcessor的实现原理,详细介绍了开发Struts应用的模型、视图和控制器的各种技术,细致的描述了Struts配置文件的每个元素的使用方法。...

    Struts1.3 备忘笔记

    06 Struts_06Filter : 中文编码的统一处理,通过Struct的请求处理器接口RequestProcessor(中央控制器)来实现 07 Struts_07ForwardAction : 访问WebRoot/WEB-INF/下文件的一种方式 08 Struts_08DynaValidatorForm : ...

    精通struts:基于mvc的java web设计与开发part1

    第4章到第7章深入探讨了Struts框架的核心组件ActionServlet和 RequestProcessor的实现原理,详细介绍了开发Struts应用的模型、视图和控制器的各种技术,细致的描述了Struts配置文件的每个元素的使用方法。...

    Struts_config.xml详解

    roles="" //指定允许调用该Action的安全角色,多个角色之间用,隔开,在处理请求时,RequestProcessor会根据该配置项来决定用户是否有权限调用Action权限。 scope="request" //指定ActionForm Bean的存在范围,可...

    java三大框架

    Struts实现的重点在C(Controller),包括ActionServlet/RequestProcessor和我们定制的 Action,也为V(View)提供了一系列定制标签(Custom Tag)。但Struts几乎没有涉及M(Model),所以Struts可以采用JAVA实现的任何形式...

    火炬博客系统5

    本系统使用 Spring 的DelegatingRequestProcessor 覆盖 Struts 的 RequestProcessor,将 Struts 动作整合到 Spring 框架中。 Spring框架是轻量级组件部署和运行的容器,可以很好的支持AOP(面向切面编程)的...

    火炬博客系统7

    本系统使用 Spring 的DelegatingRequestProcessor 覆盖 Struts 的 RequestProcessor,将 Struts 动作整合到 Spring 框架中。 Spring框架是轻量级组件部署和运行的容器,可以很好的支持AOP(面向切面编程)的...

Global site tag (gtag.js) - Google Analytics