ITEEDU

Struts Gossip: 简介 Action

在请求来临后,RequestProcessor 根据请求URI呼叫对应的Action对象,将工作交给它,并在最后由Action对象得到一个ActionForward对象, ActionServlet使用ActionForward得知将流程forward至指定的资源。

当请求到达时,会检查对应的Action对象是否存在,如果不存在则生成一个,之后一直使用它,由于Action对象会一直存在,所以使用Action对象必须注意到执行绪安全问题。

Action类别的使用是继承它,在Struts 1.1后会重新定义execute()方法,在Struts 1.0中的perform()方法已经不建议使用;execute()方法有两个接收不同参数的版本:
public ActionForward execute(ActionMapping mapping, 
                             ActionForm form, 
                             ServletRequest request, 
                             ServletResponse response) 
                                 throws Exception;

public ActionForward execute(ActionMapping mapping, 
                             ActionForm form, 
                             HttpServletRequest request, 
                             HttpServletResponse response) 
                                 throws Exception;
由于Action通常处理HTTP相关请求,所以常会使用第二个方法,execute()方法最后要传回ActionForward对象给 RequestProcessor,来回顾一下 第一个 Struts 程序 中的HelloAction的例子:
HelloAction.java
package onlyfun.caterpillar;

import java.util.*;
import javax.servlet.http.*;
import org.apache.struts.action.*;

public class HelloAction extends Action {
public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {

// get information from request object
String username = request.getParameter("user");

// no more carrying information from client
request.removeAttribute("user");

// prepare model
Map model = new HashMap();
if(username != null)
model.put("username", username);
else
model.put("username", "nobody");

// pass information to View by using reqeust object
request.setAttribute("userInfo", model);

return mapping.findForward("helloUser");
}
}
这要配合struts-config.xml中的请求URI与对应的Action设定,所以改写 第一个 Struts 程序 的struts-config.xml设定:
struts-config.xml
<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE struts-config PUBLIC
 "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
 "http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd">
<struts-config>
    <global-forwards>
        <forward
            name="welcome"
            path="/welcome.do"/>
    </global-forwards>

    <action-mappings>
        <action
             path="/welcome
             type="org.apache.struts.actions.ForwardAction"
             patameter="/WEB-INF/pages/welcome.jsp"/>

        <action
             path="/hello"
             type="onlyfun.caterpillar.HelloAction">
             <forward
                 name="helloUser"
                 path="/WEB-INF/pages/hello.jsp"/>
         </action>
     <action-mappings>
</struts-config>
在 MVC / Model 2 中,理想上所有客户端的请求都经由Controller来协调转发,客户端不会直接指定真正的地址来请求资源,您可以将资源放在/WEB-INF目录下 (如例子中的/WEB-INF/pages/hello.jsp),如此客户端就只能透过Controller的转发取得资源。

在上面使用了一个Struts所提供的org.apache.struts.actions.ForwardAction类别,它是 Action的一个子类,当客户端请求了/welcome.do时,就会呼叫这个Action,它会直接进行请求转发,转发的对象是parameter中 所设定的对象,一个应用的例子是当使用者请求的参数或方式错误时,可以使用mapping.findForward("welcome")来将使用者转发 至welcome.jsp页面。

有时候您也会需要引入一个页面或资源,这时您可以使用org.apache.struts.actions.IncludeAction,同样的也是 Action子类,其设定方式与ForwardAction相同,只不过它是用 include的方式来调用页面或资源:
...
       <action 
            path="/someresource" 
            type="org.apache.struts.actions.IncludeAction" 
            parameter="/path/someResource"/>
 ...
Action对象是Controller的一部份,在Action对象中的逻辑最好只与Web层的资料准备有关,而不涉及业务逻辑,基本上在Action 中您所要作的是:
  • 取得请求中的相关参数(或是从窗体对象中取得)
  • 验证数据的逻辑正确性
  • 将请求参数复制给商务对象
  • 取得执行结果并准备View所需的数据Model
  • 转发给View物件