定制Struts控制器组件

在Struts API中,org.apache.struts.action.RequestProcessor类真正包含了Struts控制器在处理servlet请求时所遵循的控制逻辑。控制器核心组件ActionServlet就是通过调用RequestProcessor对象的process()方法来委托其处理客户端请求的,该方法格式如下:

public void process(public void process(

    javax.servlet.http.HttpServletRequest request,

    javax.servlet.http.HttpServletResponse response)

      throws java.io.IOException, javax.servlet.ServletException{ … }

RequestProcessor类中还定义了多个processXXX()方法,process()方法正是通过调用他们来具体的处理工作的。下表中对其中重要的几个做简单介绍:

    表1 RequestProcessor类的主要处理方法

              方      法                                                 功      能

 protected String processPath()   获取客户端请求的路径URI
 protected ActionForm processActionForm()    获取当前请求表单所映射的ActionForm Bean
 protected ActionMapping processMapping()  根据请求URI获取所需的映射信息
 protected Action processActionCreate()      初始化相应的ActionBean
 protected ActionForward processActionPerform()  调用Action Bean的execute()方法处理请求
 protected void processForwardConfig()  处理由Action Bean的execute()方法返回的ActionForward对象。

 

对于多应用模块的 Struts应用,每个子应用模块都有各自的 RequestProcessor实例。当子应用模块被选择时,就会调用子应用模块的 RequestProcessor实例的process()方法来处理请求。

(1)RequestProcessor类的process()方法

Java代码
  1. Public void process(HttpServletRequest request,HttpServletResponse response)throws IOException,ServletEXception{    
  2.      request = processMultipart(request);    
  3.     // Identify the path component we will use to select a mapping    
  4.    String path = processPath(request,response);    
  5.      if(path == null){   
  6.         return;   
  7.      }    
  8.     if(log.isDebugEnabled()){    
  9.      log.debug(“Processing a ” +request.getMethod()+”’ for path ‘”+path+”’”);    
  10.     }    
  11.   //Select a Locale for the current user if requested processLocale(request,response);    
  12. //set the content type and no-caching headers if requested processContent(request,response);    
  13. processNoCache(request,response);    
  14. //General perpse preprocessing hook    
  15. if(!processPreprocess(request,response)){ return; }    
  16. //Identify the mapping for this request    
  17. ActionMapping mapping = processMapping(request,response,path);   
  18.  if(mapping == null){ return; }   
  19.  //Check for any role request to perform this action    
  20. if(!processRoles(request,response,mapping){ return; }    
  21. //process any ActionForm bean related to this request ActionForm form = processActionForm(request,response,mapping);    
  22. processPopulate(request,response,form,mapping);    
  23. if(!processValidate(request,response,form,mapping){ return; }    
  24. //process a forward or include specified by this mapping    
  25. if(!processForward(request,response ,mapping){ return; }    
  26. if(!processInclude(request,response ,mapping){ return; }    
  27. //create or acquire the Action instance to process this request    
  28. Action action = processActionCreate(request,response ,mapping);    
  29. if(action == null){ return; }    
  30. //call the Action instance itself    
  31. ActionForward forward = processActionPerform(request,response,action,form,mapping);    
  32. //process the returned ActionForward instance    
  33. processForwardConfig(request,response,forward);    
  34. }  
Public void process(HttpServletRequest request,HttpServletResponse response)throws IOException,ServletEXception{ 
     request = processMultipart(request); 
    // Identify the path component we will use to select a mapping 
   String path = processPath(request,response); 
     if(path == null){
        return;
     } 
    if(log.isDebugEnabled()){ 
     log.debug(“Processing a ” +request.getMethod()+”’ for path ‘”+path+”’”); 
    } 
  //Select a Locale for the current user if requested processLocale(request,response); 
//set the content type and no-caching headers if requested processContent(request,response); 
processNoCache(request,response); 
//General perpse preprocessing hook 
if(!processPreprocess(request,response)){ return; } 
//Identify the mapping for this request 
ActionMapping mapping = processMapping(request,response,path);
 if(mapping == null){ return; }
 //Check for any role request to perform this action 
if(!processRoles(request,response,mapping){ return; } 
//process any ActionForm bean related to this request ActionForm form = processActionForm(request,response,mapping); 
processPopulate(request,response,form,mapping); 
if(!processValidate(request,response,form,mapping){ return; } 
//process a forward or include specified by this mapping 
if(!processForward(request,response ,mapping){ return; } 
if(!processInclude(request,response ,mapping){ return; } 
//create or acquire the Action instance to process this request 
Action action = processActionCreate(request,response ,mapping); 
if(action == null){ return; } 
//call the Action instance itself 
ActionForward forward = processActionPerform(request,response,action,form,mapping); 
//process the returned ActionForward instance 
processForwardConfig(request,response,forward); 
}


RequestProcessor类的process()方法依次执行的流程
<1>调用processMultipart():如果HTTP请求方式为POST,并且请求的contentType属性以“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(contentType)方法,设置响应结果的文档类型和字符编码。
<5>调用processNoCache():读取ControllerConfig对象的nocache属性,如果nocache==true,在响应结果中将加入特定的头参数
<6>调用processPreprocess():该方法不执行任何操作,直接返回true,子类可以覆盖这个方法,执行客户化的预处理请求操作
<7>调用processMapping():寻找和用户请求的URI匹配的ActionMapping,如果不存在,就返回错误的消息
<8>调用processRoles(): 先判断是否为Action配置了安全角色,如果配置了安全角色,就调用isUserInRole()方法判断当前用户是否具备必需的角色,如果不具备,就结束处理流程,返回错误信息。
<9>调用processActionForm(): 先检查是否为ActionMapping配置了ActionForm,如果是,则找出该实例,如果不是,则创建该实例,并且保存在适当的范围中
<10>调用processPopulate(): 如果ActionMapping配置了ActionForm实例,就先调用它的reset()方法,再把数据装到ActionForm中
<11>调用processValidate(): 如果ActionMapping配置了ActionForm,并且ActionMapping的validate属性为true,就调用ActionForm的validate()方法,如果validate()方法返回的ActionErrors对象包含ActionMessage对象,说明表单验证失败,就把ActionErrors对象存储在request范围内,再把请求转发到ActionMapping的input属性指定的Web组件。要是验证成功,就继续下面的流程
<12>调用processForward(): 判断是否在ActionMapping中配置了forward属性,如果配置了就调用RequestDispatcher的forward()方法,请求流程结束,否则继续下一步。 <13>调用processInclude(): 判断是否在ActionMapping中配置了include属性,是的话接调用RequestDispatcher的include()方法,流程结束,否则继续下一步
<14>调用processActionCreate():先判断Action缓存中是否存在这个Action的实例,如果不存在就创建一个Action实例,并且保存在Action缓存中。
<15>调用processActionPerform():该方法再调用Action实例的execute()方法
<16>调用processActionForward():把Action的execute()方法返回的ActionForward对象作为参数传给他,由它来执行请求转发或者重定向。  

 


    如果要定制ActionServlet的行为规则,其实应从RequestProcessor这个RequestProcessor类着手。要开发自己的RequestProcessor类以实现定制的控制逻辑,应遵循以下步骤:
    1) 创建一个子类继承org.apache.struts.action.RequestProcessor类,在该子类中显式定义(或使用缺省的)无参、方法体为空的构造方法。
    2) 重写所需要的方法,加入定制功能。
    3) 将该子类编译后得到的class文件保存到Struts应用程序的WEB-INF/class/目录下
    4) 修改配置文件struts-config.xml,在其中加入一个名为<controller>的元素,用以指定客户定制的RequestProcessor类。
    在展示一个具体的实现定制功能的例子之前,有必要介绍一下RequestProcessor类中定义的另外几个有关方法:
 protected void log(java.lang.String message){…}
    功能:将参数String对象message的内容存入当前应用程序日志文件。
 protected void log(java.lang.String message, java.lang.Throwable exception) {…}
    功能:将参数String对象message和异常对象exception所封装的信息存入当前应用程序日志文件。
 protected boolean processPreprocess(javax.servlet.http.HttpServletRequest request,
  javax.servlet.http.HttpServletResponse response) {…}
    功能:专门用于在子类中被重写,加入由开发者定制的预处理功能。
    在RequestProcessor类中定义的processPreprocess()方法什么也不做,只是简单返回一个boolean类型值true,用以告知RequestProcessor继续后续处理程序。在定制RequestProcessor类时通常会重写此方法,注意一定要在方法的结尾返回true,如果重写如果返回值为false,则RequestProcessor对象终止对请求的处理,将控制权送回给ActionServlet的doPost()或doGet()方法。

    下面给出用户定制RequestProcessor组件的具体实现步骤:
    1)为已有的Struts应用程序创建用户自己的RequestProcessor类,重写其中的processPreprocess()方法,加入所需的控制逻辑。范例源代码如下:

源文件:MyRequestProcessor.java

package test;

import java.util.Enumeration;

import javax.servlet.http.*;

import org.apache.struts.action.RequestProcessor;

 

public class MyRequestProcessor extends RequestProcessor {

     public MyRequestProcessor() {} 

     public boolean processPreprocess(HttpServletRequest request,

            HttpServletResponse response) {               

            log("-------------- My Logging Start--------------");

            log("Request URI = " + request.getRequestURI());

            log("Context Path = " + request.getContextPath());                         

            Enumeration headerNames = request.getHeaderNames();

            log("Request Header:");

            while (headerNames.hasMoreElements()) {

                   String headerName =(String)headerNames.nextElement();

                   Enumeration headerValues =  request.getHeaders(headerName);

                   while (headerValues.hasMoreElements()) {

                          String headerValue =(String)headerValues.nextElement();

                          log("/t" + headerName + " = " + headerValue);

                   }                  

            }

            log("Locale = " + request.getLocale());

            log("Method = " + request.getMethod());

            log("Path Info = " + request.getPathInfo());

            log("Protocol = " + request.getProtocol());

            log("Remote Address = " + request.getRemoteAddr());

            log("Remote Host = " + request.getRemoteHost());

            log("Remote User = " + request.getRemoteUser());

            log("Requested Session Id = "

                   + request.getRequestedSessionId());

            log("Scheme = " + request.getScheme());

            log("Server Name = " + request.getServerName());

            log("Server Port = " + request.getServerPort());

            log("Servlet Path = " + request.getServletPath());

            log("Secure = " + request.isSecure());

            log("-------------- My Logging End  --------------");

            return true;

     }

}


    2)编译源文件MyRequestProcessor.java,将所生成的字节码文件(包括所在的package子目录)保存到Struts 应用程序的"WEB-INF/classes/"目录下。
    3)修改此Struts应用程序配置文件struts-config.xml,在其中加入<controller>元素:

    源文件:struts-config.xml

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE struts-config PUBLIC

     "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"

     "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">

<struts-config>

   ……

     <controller processorClass="test.MyRequestProcessor" /> 

</struts-config>


    说明:其他组成页面、类设计和应用程序配置均不需做改变。
    4)发布Struts应用程序,并通过客户端浏览器访问该应用程序。
    5)打开Web服务器日志文件<WAS_HOME>/logs/localhost_log.<当天日期>.txt,可以看到新加入的用户定制信息:
    2004-09-24 00:30:28 StandardContext[/myStrutsApp3]action:
-------------- My Logging Start--------------
 Request URI = /myStrutsApp3/regist.do
 Context Path = /myStrutsApp3
 Request Header:
         accept = image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,
    application/vnd.ms-powerpoint, application/vnd.ms-excel,
    application/msword , application/x-shockwave-flash, */*
         referer = http://localhost:8080/myStrutsApp3/
         accept-language = zh-cn
         content-type = application/x-www-form-urlencoded
         accept-encoding = gzip, deflate
         user-agent = Mozilla/4.0 (compatible; MSIE 6.0;
     Windows NT 5.1; .NET CLR 1.1.4322)
         host = localhost:8080
         content-length = 20
         connection = Keep-Alive
         cache-control = no-cache
         cookie = JSESSIONID=FD8A69F16E329A362DB219596897D6DA
 Locale = zh_CN
 Method = POST
 Path Info = null
 Protocol = HTTP/1.1
 Remote Address = 127.0.0.1
 Remote Host = 127.0.0.1
 Remote User = null
 Requested Session Id = FD8A69F16E329A362DB219596897D6DA
 Scheme = http
 Server Name = localhost
 Server Port = 8080
 Servlet Path = /regist.do
 Secure = false
 -------------- My Logging End  --------------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值