对於Struts,一个ActionMapping只会生成一个Action物件,当请求到达时,会检查所需的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物件给ActionServlet。
在MVC/Model 2中,理想上所有的请求都经由ActionServlet来协调转发,客户端不会直接指定真正的位址来请求资源,我们下面直接来看个例子,使用Action物件处理这个功能,首先撰写一个Action类别:
GetAction.java
package onlyfun.caterpillar;
import javax.servlet.http.*;
import org.apache.struts.action.*;
public class GetAction extends Action {
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
String resource = request.getParameter("resource");
if(resource != null && resource.length() != 0) {
request.setAttribute("resource", resource);
return mapping.findForward("resource");
// return new ActionForward("resource");
}
return mapping.findForward("welcome");
}
} 在这个类别中,如果客户端的请求中包括了请求参数resource,则直接返回一个ActionForward,对象为请求参数的内容,原本我们应该是return new ActionForward("resource"),不过为了说明方便,我们将查找struts-config.xml中的forward对象,如果客户端没有包括resource对象,则直接查找"welcome"的forward对象。
这个类别编译过後,应该位於WEB-INF下并包括package阶层,接著我们要在struts-config.xml中加以定义:
struts-config.xml
<struts-config>
<global-forwards>
<forward
name="welcome"
path="/Welcome.do"/>
</global-forwards>
<action-mappings>
<action
path="/Welcome"
type="org.apache.struts.actions.ForwardAction"
parameter="/pages/Welcome.jsp"/>
<action
path="/GetAction"
type="onlyfun.caterpillar.GetAction">
<forward
name="resource"
path="/pages/showres.jsp"/>
</action>
</action-mappings>
<message-resources parameter="resources.application"/>
</struts-config> 在<action-mappings>定义中,如果是/GetAction开头的URI请求,都会交给GetAction物件来处理,其中<forward>标签定义了如果查找"resource"的forward对象,实际该forward的路径, showres.jsp的内容如下,只是简单的显示请求资源的路径而已:
showres.jsp
<%@ taglib uri="/tags/struts-bean" prefix="bean" %>
<%@ taglib uri="/tags/struts-html" prefix="html" %>
<%@page contentType="text/html; charset=Big5"%>
<html:html locale="true">
<head>
<title><bean:message key="welcome.title"/></title>
<html:base/>
</head>
<body bgcolor="white">
<H1>请求资源 ${ resource }</H1>
</body>
</html:html> 启动Servlet容器,并使用http://localhost:8080/HelloStruts/GetAction.do?resource=/images/struts.jpg来浏览,您会得到以下的内容:
<html lang="zh">
<head>
<title>哈罗!Struts!</title>
<base href="http://localhost:8080/HelloStruts/pages/showres.jsp">
</head>
<body bgcolor="white">
<H1>请求资源 /images/struts.jpg</H1>
</body>
</html> Action物件是执行工作的物件,它主要的工作通常有:
*验证使用者的进程状态
*进一步验证表单物件的资讯
*更新应用程式中物件的状态
*处理客户端的请求
*返回ActionForward给ActionServlet
为了要能够重用Action物件,通常建议不要在Action中加入过多的逻辑,普遍认为Action物件也应属於控制器角色,除了以上必要的工作之外,建议将与业务相关的工作交给辅助类别,减少Action物件中的逻辑,以使得Action物件容易理解它的职责。
基本上不只有Action物件应保持职责清晰,就Struts而言,它的工作是辅助建议MVC/Model 2架构,每个相关的组件除了这个目的之外,没有其它的目的,Struts建立起来的架构也鼓励重用,应当将业务相关的逻辑交由其它的物件来处理,而不是交给Struts组件。