第一個(gè)Struts 應用:helloapp
應用
本章講解了一個(gè)簡(jiǎn)單的Struts應用例子——helloapp 應用,這個(gè)例子可以幫助讀者迅速
入門(mén),獲得開(kāi)發(fā)Struts 應用的基本經(jīng)驗。該應用的功能非常簡(jiǎn)單:接受用戶(hù)輸入的姓名
<name>,然后輸出“Hello <name>”。開(kāi)發(fā)helloapp應用涉及以下內容:
l 分析應用需求
l 把基于MVC設計模式的Struts框架運用到應用中
l 創(chuàng )建視圖組件,包括HTML表單(hello.jsp)和ActionForm Bean(HelloForm.java)
l 創(chuàng )建application.properties資源文件
l 數據驗證,包括表單驗證和業(yè)務(wù)邏輯驗證
l 創(chuàng )建控制器組件:HelloAction.java
l 創(chuàng )建模型組件:PersonBean.java
l 創(chuàng )建包含被各個(gè)模塊共享的常量數據的Java 文件:Constants.java
l 創(chuàng )建配置文件:web.xml 和struts-config.xml
l 編譯、發(fā)布和運行helloapp應用
2.1 分析helloapp 應用的需求
在開(kāi)發(fā)應用時(shí),首先從分析需求入手,列舉該應用的各種功能,以及限制條件。helloapp
應用的需求非常簡(jiǎn)單,其包括如下需求:
l 接受用戶(hù)輸入的姓名<name>,然后返回字符串“Hello <name> !”。
l 如果用戶(hù)沒(méi)有輸入姓名就提交表單,將返回出錯信息,提示用戶(hù)首先輸入姓名。
l 如果用戶(hù)輸入姓名為“Monster”,將返回出錯信息,拒絕向“Monster”打招呼。
l 為了演示模型組件的功能,本應用使用模型組件來(lái)保存用戶(hù)輸入的姓名。
2.2 運用Struts 框架
下面把Struts框架運用到helloapp應用中。Struts框架可以方便迅速地把一個(gè)復雜的應
用劃分成模型、視圖和控制器組件,而Struts的配置文件struts-config.xml 則可以靈活地組
裝這些組件,簡(jiǎn)化開(kāi)發(fā)過(guò)程。
以下是helloapp應用的各個(gè)模塊的構成:
PDF 文件使用 "pdfFactory" 試用版本創(chuàng )建
www.fineprint.com.cn精通Struts:基于MVC的Java Web設計與開(kāi)發(fā)
20
l 模型包括一個(gè)JavaBean 組件PersonBean,它有一個(gè)userName 屬性,代表用戶(hù)輸
入的名字。它提供了get/set 方法,分別用于讀取和設置userName 屬性,它還提
供一個(gè)save()方法,負責把userName屬性保存到持久化存儲系統中,如數據庫或
文件系統。對于更為復雜的Web 應用,JavaBean組件可以作為EJB 或Web 服務(wù)
的前端組件。
l 視圖包括一個(gè)JSP 文件hello.jsp,它提供用戶(hù)界面,接受用戶(hù)輸入的姓名。視圖
還包括一個(gè)ActionForm Bean,它用來(lái)存放表單數據,并進(jìn)行表單驗證,如果用戶(hù)
沒(méi)有輸入姓名就提交表單,將返回出錯信息。
l 控制器包括一個(gè)Action類(lèi)HelloAction,它完成三項任務(wù):一是進(jìn)行業(yè)務(wù)邏輯驗證,
如果用戶(hù)輸入的姓名為“Monster”,將返回錯誤消息;二是調用模型組件
PersonBean 的save()方法,保存用戶(hù)輸入的名字;三是決定將合適的視圖組件返
回給用戶(hù)。
除了創(chuàng )建模型、視圖和控制器組件,還需要創(chuàng )建Struts 的配置文件struts-config.xml,
它可以把這些組件組裝起來(lái),使它們協(xié)調工作。此外,還需要創(chuàng )建整個(gè)Web應用的配置文
件web.xml。
2.3 創(chuàng )建視圖組件
在本例中,視圖包括兩個(gè)組件:
l 一個(gè)JSP文件:hello.jsp。
l 一個(gè)ActionForm Bean:HelloForm Bean。
下面分別講述如何創(chuàng )建這兩個(gè)組件。
2.3.1 創(chuàng )建JSP文件
hello.jsp 提供用戶(hù)界面,能夠接受用戶(hù)輸入的姓名。此外,本W(wǎng)eb 應用的所有輸出結
果也都由hello.jsp顯示給用戶(hù)。圖2-1顯示了hello.jsp提供的網(wǎng)頁(yè)。
圖2-1 hello.jsp的網(wǎng)頁(yè)
在圖2-1中,當用戶(hù)輸入姓名“Weiqin”后,單擊【Submit】按鈕提交表單,本應用將
返回“Hello Weiqin!”,參見(jiàn)圖2-2。
PDF 文件使用 "pdfFactory" 試用版本創(chuàng )建
www.fineprint.com.cn第2 章 第一個(gè)Struts應用:helloapp應用
21
圖2-2 hello.jsp接受用戶(hù)輸入后正常返回的網(wǎng)頁(yè)
例程2-1為hello.jsp文件的源代碼。
例程2-1 hello.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<html:html locale="true">
<head>
<title><bean:message key="hello.jsp.title"/></title>
<html:base/>
</head>
<body bgcolor="white"><p>
<h2><bean:message key="hello.jsp.page.heading"/></h2><p>
<html:errors/><p>
<logic:present name="personbean" scope="request">
<h2>
<bean:message key="hello.jsp.page.hello"/>
<bean:write name="personbean" property="userName" />!<p>
</h2>
</logic:present>
<html:form action="/HelloWorld.do" focus="userName" >
<bean:message key="hello.jsp.prompt.person"/>
<html:text property="userName" size="16" maxlength="16"/><br>
<html:submit property="submit" value="Submit"/>
<html:reset/>
</html:form><br>
PDF 文件使用 "pdfFactory" 試用版本創(chuàng )建
www.fineprint.com.cn精通Struts:基于MVC的Java Web設計與開(kāi)發(fā)
22
<html:img page="/struts-power.gif" alt="Powered by Struts"/>
</body>
</html:html>
以上基于Struts框架的JSP文件有以下特點(diǎn):
l 沒(méi)有任何Java 程序代碼。
l 使用了許多Struts的客戶(hù)化標簽,例如<html:form>和<logic:present>標簽。
l 沒(méi)有直接提供文本內容,取而代之的是<bean:message>標簽,輸出到網(wǎng)頁(yè)上的文
本內容都是由<bean:message>標簽來(lái)生成的。例如:
<bean:message key="hello.jsp.prompt.person"/>
Struts客戶(hù)化標簽是聯(lián)系視圖組件和Struts框架中其他組件的紐帶。這些標簽可以訪(fǎng)問(wèn)
或顯示來(lái)自于控制器和模型組件的數據。在本書(shū)第12 章至第16 章將專(zhuān)門(mén)介紹Struts 標簽
的用法,本節先簡(jiǎn)單介紹幾種重要的Struts標簽。
hello.jsp開(kāi)頭幾行用于聲明和加載Struts標簽庫:
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
以上代碼表明該JSP文件使用了Struts Bean、Html 和Logic 標簽庫,這是加載客戶(hù)化
標簽庫的標準JSP語(yǔ)法。
hello.jsp中使用了來(lái)自 Struts HTML標簽庫中的標簽,包括<html:errors>, <html:form>
和<html:text>:
l <html:errors>:用于顯示Struts框架中其他組件產(chǎn)生的錯誤消息。
l <html:form>:用于創(chuàng )建HTML 表單,它能夠把HTML 表單的字段和ActionForm
Bean的屬性關(guān)聯(lián)起來(lái)。
l <html:text>:該標簽是<html:form>的子標簽,用于創(chuàng )建HTML表單的文本框。它
和ActionForm Bean的屬性相關(guān)聯(lián)。
hello.jsp中使用了來(lái)自Struts Bean標簽庫的兩個(gè)標簽<bean:message>和<bean:write>:
l <bean:message>:用于輸出本地化的文本內容,它的key屬性指定消息key,與消
息key匹配的文本內容來(lái)自于專(zhuān)門(mén)的Resource Bundle,關(guān)于Resource Bundle的概
念參見(jiàn)本書(shū)第9 章(Struts應用的國際化)。
l <bean:write>:用于輸出JavaBean 的屬性值。本例中,它用于輸出personbean 對
象的userName屬性值:
<bean:write name="personbean" property="userName" />
hello.jsp 使用了來(lái)自Struts Logic 標簽庫的<logic:present>標簽。<logic:present>標簽用
來(lái)判斷JavaBean 在特定的范圍內是否存在,只有當JavaBean 存在時(shí),才會(huì )執行標簽主體
中的內容:
<logic:present name="personbean" scope="request">
<h2>
PDF 文件使用 "pdfFactory" 試用版本創(chuàng )建
www.fineprint.com.cn第2 章 第一個(gè)Struts應用:helloapp應用
23
Hello <bean:write name="personbean" property="userName" />!<p>
</h2>
</logic:present>
在本例中,<logic:present>標簽用來(lái)判斷在request 范圍內是否存在personbean 對象,
如果存在,就輸出personbean 的userName 屬性值。與<logic:present>標簽相對的是
<logic:notPresent>標簽,它表示只有當JavaBean 在特定的范圍內不存在時(shí),才會(huì )執行標簽
主體中的內容。
2.3.2 創(chuàng )建消息資源文件
hello.jsp使用<bean:message>標簽來(lái)輸出文本內容。這些文本來(lái)自于Resource Bundle,
每個(gè)Resource Bundle 都對應一個(gè)或多個(gè)本地化的消息資源文件,本例中的資源文件為
application.properties,例程2-2是該消息資源文件的內容。
例程2-2 application.properties文件
#Application Resources for the "Hello" sample application
hello.jsp.title=Hello - A first Struts program
hello.jsp.page.heading=Hello World! A first Struts application
hello.jsp.prompt.person=Please enter a UserName to say hello to :
hello.jsp.page.hello=Hello
#Validation and error messages for HelloForm.java and HelloAction.java
hello.dont.talk.to.monster=We don‘t want to say hello to Monster!!!
hello.no.username.error=Please enter a <i>UserName</i> to say hello to!
以上文件以“消息key/消息文本”的格式存放數據,文件中“#”的后面為注釋行。對
于以下JSP代碼:
<bean:message key="hello.jsp.title"/>
<bean:message>標簽的key 屬性為“hello.jsp.tilte”,在Resource Bundle 中與之匹配的
內容為:
hello.jsp.title=Hello - A first Struts program
因此,以上<bean:message>標簽將把“Hello - A first Struts program”輸出到網(wǎng)頁(yè)上。
2.3.3 創(chuàng )建ActionForm Bean
當用戶(hù)提交了HTML 表單后,Struts 框架將自動(dòng)把表單數據組裝到ActionForm Bean
中。ActionForm Bean中的屬性和HTML表單中的字段一一對應。ActionForm Bean還提供
數據驗證方法,以及把屬性重新設置為默認值的方法。Struts 框架中定義的ActionForm 類(lèi)
是抽象的,必須在應用中創(chuàng )建它的子類(lèi),來(lái)存放具體的HTML 表單數據。例程2-3 為
HelloForm.java 的源程序, 它用于處理hello.jsp中的表單數據。
PDF 文件使用 "pdfFactory" 試用版本創(chuàng )建
www.fineprint.com.cn精通Struts:基于MVC的Java Web設計與開(kāi)發(fā)
24
例程2-3 HelloForm.java
package hello;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
public final class HelloForm extends ActionForm {
private String userName = null;
public String getUserName() {
return (this.userName);
}
public void setUserName(String userName) {
this.userName = userName;
}
/**
* Reset all properties to their default values.
*/
public void reset(ActionMapping mapping, HttpServletRequest request) {
this.userName = null;
}
/**
* Validate the properties posted in this request. If validation errors are
* found, return an <code>ActionErrors</code> object containing the errors.
* If no validation errors occur, return <code>null</code> or an empty
* <code>ActionErrors</code> object.
*/
public ActionErrors validate(ActionMapping mapping,
HttpServletRequest request) {
ActionErrors errors = new ActionErrors();
if ((userName == null) || (userName.length() < 1))
errors.add("username", new ActionMessage("hello.no.username.error"));
return errors;
}
}
PDF 文件使用 "pdfFactory" 試用版本創(chuàng )建
www.fineprint.com.cn第2 章 第一個(gè)Struts應用:helloapp應用
25
從以上代碼中可以看出,ActionForm Bean 實(shí)質(zhì)上是一種JavaBean,不過(guò)它除了具有
JavaBean的常規方法,還有兩種特殊方法:
l validate():用于表單驗證。
l reset():把屬性重新設置為默認值。
2.3.4 數據驗證
幾乎所有和用戶(hù)交互的應用都需要數據驗證,而從頭設計并開(kāi)發(fā)完善的數據驗證機制
往往很費時(shí)。幸運的是,Struts框架提供了現成的、易于使用的數據驗證功能。Struts框架
的數據驗證可分為兩種類(lèi)型:表單驗證和業(yè)務(wù)邏輯驗證,在本例中,它們分別運用于以下
場(chǎng)合:
l 表單驗證:如果用戶(hù)沒(méi)有在表單中輸入姓名就提交表單,將生成表單驗證錯誤。
l 業(yè)務(wù)邏輯驗證:如果用戶(hù)在表單中輸入的姓名為“Monster”,按照本應用的業(yè)務(wù)
規則,即不允許向“Monster”打招呼,因此將生成業(yè)務(wù)邏輯錯誤。
第一種類(lèi)型的驗證,即表單驗證由ActionForm Bean 來(lái)負責處理。在本例中,
HelloForm.java 的validate()方法負責完成這一任務(wù):
public ActionErrors validate(ActionMapping mapping,
HttpServletRequest request) {
ActionErrors errors = new ActionErrors();
if ((userName == null) || (userName.length() < 1))
errors.add("username", new ActionMessage("hello.no.username.error"));
return errors;
}
}
當用戶(hù)提交了HTML 表單后,Struts 框架將自動(dòng)把表單數據組裝到ActionForm Bean
中。接下來(lái)Struts 框架會(huì )自動(dòng)調用ActionForm Bean 的validate()方法進(jìn)行表單驗證。如果
validate()方法返回的ActionErrors 對象為null,或者不包含任何ActionMessage對象,就表
示沒(méi)有錯誤,數據驗證通過(guò)。如果ActionErrors中包含ActionMessage對象,就表示發(fā)生了
驗證錯誤,Struts 框架會(huì )把ActionErrors 對象保存到request 范圍內,然后把請求轉發(fā)到恰
當的視圖組件,視圖組件通過(guò)<html:errors>標簽把request 范圍內的ActionErrors 對象中包
含的錯誤消息顯示出來(lái),提示用戶(hù)修改錯誤。
在Struts 早期的版本中使用ActionError 類(lèi)來(lái)表示錯誤消息,
ActionError 類(lèi)是ActionMessage的子類(lèi)。Struts 1.2 將廢棄ActionError,統
一采用ActionMessage類(lèi)來(lái)表示正?;蝈e誤消息。
第二種類(lèi)型的驗證,即業(yè)務(wù)邏輯驗證由Action來(lái)負責處理,參見(jiàn)本章的2.4.3 小節。
PDF 文件使用 "pdfFactory" 試用版本創(chuàng )建
www.fineprint.com.cn精通Struts:基于MVC的Java Web設計與開(kāi)發(fā)
26
2.4 創(chuàng )建控制器組件
控制器組件包括ActionServlet 類(lèi)和Action 類(lèi)。ActionServlet 類(lèi)是Struts 框架自帶的,
它是整個(gè)Struts 框架的控制樞紐,通常不需要擴展。Struts 框架提供了可供擴展的Action
類(lèi),它用來(lái)處理特定的HTTP請求,例程2-4為HelloAction類(lèi)的源程序。
例程2-4 HelloAction.java
package hello;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.util.MessageResources;
public final class HelloAction extends Action {
/**
* Process the specified HTTP request, and create the corresponding HTTP
* response (or forward to another web component that will create it).
* Return an <code>ActionForward</code> instance describing where and how
* control should be forwarded, or <code>null</code> if the response has
* already been completed.
*/
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
// These "messages" come from the ApplicationResources.properties file
MessageResources messages = getResources(request);
/*
* Validate the request parameters specified by the user
PDF 文件使用 "pdfFactory" 試用版本創(chuàng )建
www.fineprint.com.cn第2 章 第一個(gè)Struts應用:helloapp應用
27
* Note: Basic field validation done in HelloForm.java
* Business logic validation done in HelloAction.java
*/
ActionMessages errors = new ActionMessages();
String userName = (String)((HelloForm) form).getUserName();
String badUserName = "Monster";
if (userName.equalsIgnoreCase(badUserName)) {
errors.add("username", new ActionMessage("hello.dont.talk.to.monster",
badUserName ));
saveErrors(request, errors);
return (new ActionForward(mapping.getInput()));
}
/*
* Having received and validated the data submitted
* from the View, we now update the model
*/
PersonBean pb = new PersonBean();
pb.setUserName(userName);
pb.saveToPersistentStore();
/*
* If there was a choice of View components that depended on the model
* (or some other) status, we‘d make the decision here as to which
* to display. In this case, there is only one View component.
*
* We pass data to the View components by setting them as attributes
* in the page, request, session or servlet context. In this case, the
* most appropriate scoping is the "request" context since the data
* will not be neaded after the View is generated.
*
* Constants.PERSON_KEY provides a key accessible by both the
* Controller component (i.e. this class) and the View component
* (i.e. the jsp file we forward to).
*/
request.setAttribute( Constants.PERSON_KEY, pb);
// Remove the Form Bean - don‘t need to carry values forward
request.removeAttribute(mapping.getAttribute());
// Forward control to the specified success URI
return (mapping.findForward("SayHello"));
}
PDF 文件使用 "pdfFactory" 試用版本創(chuàng )建
www.fineprint.com.cn精通Struts:基于MVC的Java Web設計與開(kāi)發(fā)
28
}
HelloAction.java 是本應用中最復雜的程序,下面分步講解它的工作機制和流程。
2.4.1 Action類(lèi)的工作機制
所有的Action類(lèi)都是org.apache.struts.action.Action的子類(lèi)。Action子類(lèi)應該覆蓋父類(lèi)
的execute()方法。當ActionForm Bean 被創(chuàng )建,并且表單驗證順利通過(guò)后, Struts 框架就
會(huì )調用Action類(lèi)的execute()方法。execute()方法的定義如下:
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException ;
execute()方法包含以下參數:
l ActionMapping:包含了這個(gè)Action 的配置信息,和struts-config.xml 文件中的
<action>元素對應。
l ActionForm:包含了用戶(hù)的表單數據,當Struts 框架調用execute()方法時(shí),
ActionForm中的數據已經(jīng)通過(guò)了表單驗證。
l HttpServletRequest:當前的HTTP請求對象。
l HttpServletResponse:當前的HTTP響應對象。
Action類(lèi)的execute()方法返回ActionForward對象,它包含了請求轉發(fā)路徑信息。
2.4.2 訪(fǎng)問(wèn)封裝在MessageResources中的本地化文本
在本例中,Action類(lèi)的execute()方法首先獲得MessageResources 對象:
MessageResources messages = getResources(request);
在A(yíng)ction類(lèi)中定義了getResources(HttpServletRequest request)方法,該方法返回當前默
認的MessageResources 對象,它封裝了Resource Bundle 中的文本內容。接下來(lái)Action類(lèi)
就可以通過(guò)MessageResources 對象來(lái)訪(fǎng)問(wèn)文本內容。例如,如果要讀取消息key 為
“hello.jsp.title”對應的文本內容,可以調用MessageResources 類(lèi)的getMessage(String key)
方法:
String title=messages.getMessage("hello.jsp.title");
2.4.3 業(yè)務(wù)邏輯驗證
接下來(lái),Action類(lèi)的execute()方法執行業(yè)務(wù)邏輯驗證:
ActionMessages errors = new ActionMessages();
String userName = (String)((HelloForm) form).getUserName();
String badUserName = "Monster";
if (userName.equalsIgnoreCase(badUserName)) {
PDF 文件使用 "pdfFactory" 試用版本創(chuàng )建
www.fineprint.com.cn第2 章 第一個(gè)Struts應用:helloapp應用
29
errors.add("username", new ActionMessage("hello.dont.talk.to.monster", badUserName ));
saveErrors(request, errors);
return (new ActionForward(mapping.getInput()));
}
如果用戶(hù)輸入的姓名為“Monster”,將創(chuàng )建包含錯誤信息的ActionMessage 對象,
ActionMessage 對象被保存到ActionMessages 對象中。接下來(lái)調用在A(yíng)ction 基類(lèi)中定義的
saveErrors()方法,它負責把ActionMessages 對象保存到request 范圍內。最后返回
ActionForward對象,Struts框架會(huì )根據ActionForward對象包含的轉發(fā)信息把請求轉發(fā)到恰
當的視圖組件,視圖組件通過(guò)<html:errors>標簽把request 范圍內的ActionMessages 對象中
包含的錯誤消息顯示出來(lái),提示用戶(hù)修改錯誤。
在2.3.4小節中還提到了ActionErrors對象。圖2-3顯示了ActionMessages、ActionErrors、
ActionMessage 和ActionError 類(lèi)的類(lèi)框圖。ActionErrors 繼承ActionMessages,ActionError
繼承ActionMessage,ActionMessages 和ActionMessage 之間為聚集關(guān)系,即一個(gè)
ActionMessages 對象中可以包含多個(gè)ActionMessage對象。(圖中的0..n表述是否正確?)
圖2-3 ActionMessages、ActionErrors、ActionMessage和ActionError 類(lèi)的類(lèi)框圖
表單驗證通常只對用戶(hù)輸入的數據進(jìn)行簡(jiǎn)單的語(yǔ)法和格式檢查,而業(yè)務(wù)邏輯驗證會(huì )對
數據進(jìn)行更為復雜的驗證。在很多情況下,需要模型組件的介入,才能完成業(yè)務(wù)邏輯驗證。
2.4.4 訪(fǎng)問(wèn)模型組件
接下來(lái),HelloAction 類(lèi)創(chuàng )建了一個(gè)模型組件PersonBean 對象,并調用它的
saveTopersistentStore()saveToPersistentStore()方法來(lái)保存userName屬性:
PersonBean pb = new PersonBean();
pb.setUserName(userName);
pb.saveToPersistentStore();
本例僅提供了Action類(lèi)訪(fǎng)問(wèn)模型組件簡(jiǎn)單的例子。在實(shí)際應用中,Action類(lèi)會(huì )訪(fǎng)問(wèn)模
型組件,完成更加復雜的功能,例如:
l 從模型組件中讀取數據,用于被視圖組件顯示。
l 和多個(gè)模型組件交互。
l 依據從模型組件中獲得的信息,來(lái)決定返回哪個(gè)視圖組件。
PDF 文件使用 "pdfFactory" 試用版本創(chuàng )建
www.fineprint.com.cn精通Struts:基于MVC的Java Web設計與開(kāi)發(fā)
30
2.4.5 向視圖組件傳遞數據
Action 類(lèi)把數據存放在request 或session 范圍內,以便向視圖組件傳遞信息。以下是
HelloAction.java 向視圖組件傳遞數據的代碼:
request.setAttribute( Constants.PERSON_KEY, pb);
// Remove the Form Bean - don‘t need to carry values forward
request.removeAttribute(mapping.getAttribute());
以上代碼完成兩件事:
l 把PersonBean對象保存在request范圍內。
l 從request范圍內刪除ActionForm Bean。由于后續的請求轉發(fā)目標組件不再需要
HelloForm Bean,所以可將它刪除。
2.4.6 把HTTP請求轉發(fā)給合適的視圖組件
最后,Action類(lèi)把流程轉發(fā)給合適的視圖組件。
// Forward control to the specified success URI
return (mapping.findForward("SayHello"));
2.5 創(chuàng )建模型組件
在2.4 節中已經(jīng)講過(guò),Action 類(lèi)會(huì )訪(fǎng)問(wèn)模型組件。本例中模型組件為JavaBean:
PersonBean。例程2-5是PersonBean的源代碼。
例程2-5 PersonBean.java
package hello;
public class PersonBean {
private String userName = null;
public String getUserName() {
return this.userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
/**
* This is a stub method that would be used for the Model to save
* the information submitted to a persistent store. In this sample
* application it is not used.
*/
PDF 文件使用 "pdfFactory" 試用版本創(chuàng )建
www.fineprint.com.cn第2 章 第一個(gè)Struts應用:helloapp應用
31
public void saveToPersistentStore() {
/*
* This is a stub method that might be used to save the person‘s
* name to a persistent store(i.e. database) if this were a real application.
*
* The actual business operations that would exist within a Model
* component would depend upon the requirements of the application.
*/
}
}
PersonBean是一個(gè)非常簡(jiǎn)單的JavaBean,它包括一個(gè)userName屬性,以及相關(guān)的get/set
方法。此外,它還有一個(gè)業(yè)務(wù)方法saveToPersistentStore()。本例中并沒(méi)有真正實(shí)現這一方
法。在實(shí)際應用中,這個(gè)方法可以用來(lái)把JavaBean的屬性保存在持久化存儲系統中,如數
據庫或文件系統。
通過(guò)這個(gè)簡(jiǎn)單的例子,讀者可以進(jìn)一步理解Struts 框架中使用模型組件的一大優(yōu)點(diǎn),
它把業(yè)務(wù)邏輯的實(shí)現和應用的其他部分分離開(kāi)來(lái),可以提高整個(gè)應用的靈活性、可重用性
和可擴展性。如果模型組件的實(shí)現發(fā)生改變,例如本來(lái)把JavaBean 的屬性保存在MySQL
數據庫中,后來(lái)改為保存在Oracle數據庫中,此時(shí)Action類(lèi)不需要做任何變動(dòng)。不僅如此,
即使模型組件由JavaBean改為EJB,運行在遠程應用服務(wù)器上,也不會(huì )對Action類(lèi)造成任
何影響。
2.6 創(chuàng )建存放常量的Java文件
根據2.4.5 小節,HelloAction類(lèi)和視圖組件之間通過(guò)HttpServletRequest的setAttribute()
和getAttribute()方法來(lái)共享request 范圍內的數據。下面再看一下HelloAction 類(lèi)調用
HttpServletRequest的setAttribute()方法的細節。
當HelloAction 類(lèi)調用HttpServletRequest 的setAttribute()方法,向hello.jsp 傳遞
PersonBean對象時(shí),需要提供一個(gè)名為“personbean”的屬性key:
request.setAttribute("personbean",pb);
hello.jsp通過(guò)這個(gè)名為“personbean”的屬性key來(lái)讀取PersonBean對象:
<logic:present name="personbean" scope="request">
<h2>
Hello <bean:write name="personbean" property="userName" />!<p>
</h2>
</logic:present>
對于Struts應用,提倡將這些屬性key常量定義在一個(gè)Java 文件Constants.java 中,例
程2-6顯示了它的源程序。
PDF 文件使用 "pdfFactory" 試用版本創(chuàng )建
www.fineprint.com.cn精通Struts:基于MVC的Java Web設計與開(kāi)發(fā)
32
例程2-6 Constants.java
package hello;
public final class Constants {
/**
* The application scope attribute under which our user database
* is stored.
*/
public static final String PERSON_KEY = "personbean";
}
這樣,HelloAction類(lèi)可以按以下方式來(lái)調用HttpServletRequest的setAttribute()方法:
request.setAttribute( Constants.PERSON_KEY, pb);
把一些常量定義在Constants.java 中可以提高Action類(lèi)的獨立性。當屬性key常量值發(fā)
生改變時(shí),只需要修改Constants.java 文件,而不需要修改Action類(lèi)。
此外,本例把PersonBean對象保存在HttpServletRequest對象中。對于其他實(shí)際的Web
應用,也可以根據需要把JavaBean對象保存在HttpSession對象中。
2.7 創(chuàng )建配置文件
2.7.1 創(chuàng )建Web應用的配置文件
對于Struts 應用,它的配置文件web.xml 應該對ActionServlet 類(lèi)進(jìn)行配置。此外,還
應該聲明Web 應用所使用的Struts 標簽庫,本例中聲明使用了三個(gè)標簽庫:Struts Bean、
Struts HTML和Struts Logic標簽庫。例程2-7為web.xml的源代碼。
例程2-7 web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
"
<web-app>
<display-name>HelloApp Struts Application</display-name>
<!-- Standard Action Servlet Configuration -->
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
PDF 文件使用 "pdfFactory" 試用版本創(chuàng )建 www.fineprint.com.cn第2 章 第一個(gè)Struts應用:helloapp應用
33
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<!-- Standard Action Servlet Mapping -->
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<!-- The Usual Welcome File List -->
<welcome-file-list>
<welcome-file>hello.jsp</welcome-file>
</welcome-file-list>
<!-- Struts Tag Library Descriptors -->
<taglib>
<taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-html.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/struts-logic.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-logic.tld</taglib-location>
</taglib>
</web-app>
2.7.2 創(chuàng )建Struts框架的配置文件
正如前面提及的,Struts框架允許把應用劃分成多個(gè)組件,提高開(kāi)發(fā)速度。而Struts框
架的配置文件struts-config.xml可以把這些組件組裝起來(lái),決定如何使用它們。例程2-8是
helloapp應用的struts-config.xml文件的源代碼。
例程2-8 struts-config.xml
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
"
PDF 文件使用 "pdfFactory" 試用版本創(chuàng )建 www.fineprint.com.cn精通Struts:基于MVC的Java Web設計與開(kāi)發(fā)
34
<!--
This is the Struts configuration file for the "Hello!" sample application
-->
<struts-config>
<!-- ======== Form Bean Definitions =================================== -->
<form-beans>
<form-bean name="HelloForm" type="hello.HelloForm"/>
</form-beans>
<!-- ========== Action Mapping Definitions ============================== -->
<action-mappings>
<!-- Say Hello! -->
<action path = "/HelloWorld"
type = "hello.HelloAction"
name = "HelloForm"
scope = "request"
validate = "true"
input = "/hello.jsp"
>
<forward name="SayHello" path="/hello.jsp" />
</action>
</action-mappings>
<!-- ========== Message Resources Definitions =========================== -->
<message-resources parameter="hello.application"/>
</struts-config>
以上代碼對helloapp 應用的HelloForm、HelloAction 和消息資源文件進(jìn)行了配置,首
先通過(guò)<form-bean>元素配置了一個(gè)ActionForm Bean,名叫HelloForm,它對應的類(lèi)為
hello.HelloForm:
<form-bean name="HelloForm" type="hello.HelloForm"/>
接著(zhù)通過(guò)<action>元素配置了一個(gè)Action組件:
<action path = "/HelloWorld"
type = "hello.HelloAction"
name = "HelloForm"
scope = "request"
validate = "true"
input = "/hello.jsp"
>
<forward name="SayHello" path="/hello.jsp" />
</action>
PDF 文件使用 "pdfFactory" 試用版本創(chuàng )建
www.fineprint.com.cn第2 章 第一個(gè)Struts應用:helloapp應用
35
<action>元素的path屬性指定請求訪(fǎng)問(wèn)Action的路徑,type屬性指定Action的完整類(lèi)
名,name屬性指定需要傳遞給Action的ActionForm Bean,scope屬性指定ActionForm Bean
的存放范圍,validate 屬性指定是否執行表單驗證,input 屬性指定當表單驗證失敗時(shí)的轉
發(fā)路徑。<action>元素還包含一個(gè)<forward>子元素,它定義了一個(gè)請求轉發(fā)路徑。
本例中的<action>元素配置了HelloAction組件,對應的類(lèi)為hello.HelloAction,請求訪(fǎng)
問(wèn)路徑為“HelloWorld”,當Action 類(lèi)被調用時(shí),Struts 框架應該把已經(jīng)包含表單數據的
HelloForm Bean傳給它。HelloForm Bean存放在request范圍內,并且在調用Action類(lèi)之前,
應該進(jìn)行表單驗證。如果表單驗證失敗,請求將被轉發(fā)到接收用戶(hù)輸入的網(wǎng)頁(yè)hello.jsp,
讓用戶(hù)糾正錯誤。
struts-config.xml文件最后通過(guò)<message-resources>元素定義了一個(gè)Resource Bundle:
<message-resources parameter="hello.application"/>
<message-resources>元素的parameter 屬性指定Resource Bundle使用的消息資源文件。
本例中parameter 屬性為“hello.application”,表明消息資源文件名為“application.properties”,
它的存放路徑為WEB-INF/classes/hello/application.properties。
2.8 發(fā)布和運行helloapp 應用
helloapp應用作為Java Web應用,它的目錄結構應該符合Sun公司制定的Java Web 應
用的規范,此外,由于helloapp應用使用了Struts框架,因此應該把Struts框架所需的JAR
文件和標簽庫描述文件TLD 文件包含進(jìn)來(lái)。訪(fǎng)問(wèn)
http://jakarta.apache.org/builds,可以下載
最新的Struts 軟件包,把struts 壓縮文件解壓后,在其lib 子目錄下提供了Struts 框架所需
的JAR文件:
l commons-beanutils.jar
l commons-collections.jar
l commons-digester.jar
l commons-fileupload.jar
l commons-logging.jar
l commons-validator.jar
l jakarta-oro.jar
l struts.jar
在Struts軟件包的lib 子目錄下還提供了所有的Struts標簽庫描述TLD 文件:
l struts-bean.tld
l struts-html.tld
l struts-logic.tld
l struts-nested.tld
l struts-tiles.tld
圖2-4顯示了helloapp應用的目錄結構。
PDF 文件使用 "pdfFactory" 試用版本創(chuàng )建
www.fineprint.com.cn精通Struts:基于MVC的Java Web設計與開(kāi)發(fā)
36
圖2-4 helloapp應用的目錄結構
helloapp 應用的Java 源文件位于helloapp/src 目錄下,編譯這些Java 源文件時(shí),應該
把Servlet API的JAR文件以及Struts的struts.jar 文件加到classpath中。如果在本地安裝了
Tomcat 服務(wù)器,假定Tomcat 的根目錄為<CATALINA_HOME>,在<CATALINA_
HOME>\common\lib 目錄下提供了servlet-api.jar 文件。
在本書(shū)配套光盤(pán)的sourcecode/helloapp/version1/helloapp目錄下提供了該應用的所有源
文件,只要把整個(gè)helloapp子目錄拷貝到<CATALINA_HOME>/webapps下,就可以按開(kāi)放
式目錄結構發(fā)布這個(gè)應用。
如果helloapp 應用開(kāi)發(fā)完畢,進(jìn)入產(chǎn)品發(fā)布階段,應該將整個(gè)Web 應用打包為WAR
文件,再進(jìn)行發(fā)布。在本例中,也可以按如下步驟在Tomcat服務(wù)器上發(fā)布helloapp應用。
(1)在DOS下轉到helloapp應用的根目錄。
(2)把整個(gè)Web應用打包為helloapp.war 文件,命令如下:
jar cvf helloapp.war *.*
(3)把helloapp.war 文件拷貝到<CATALINA_HOME>/webapps目錄下。
(4)啟動(dòng)Tomcat 服務(wù)器。Tomcat 服務(wù)器啟動(dòng)時(shí),會(huì )把webapps 目錄下的所有WAR
文件自動(dòng)展開(kāi)為開(kāi)放式的目錄結構。所以在服務(wù)器啟動(dòng)后,會(huì )發(fā)現服務(wù)器把helloapp.war
展開(kāi)到<CATALINA_HOME> /webapps/helloapp目錄中。
PDF 文件使用 "pdfFactory" 試用版本創(chuàng )建
www.fineprint.com.cn第2 章 第一個(gè)Struts應用:helloapp應用
37
(5)通過(guò)瀏覽器訪(fǎng)問(wèn)
http://localhost:8080/helloapp/hello.jsp。
2.8.1 服務(wù)器端裝載hello.jsp的流程
在Tomcat 服務(wù)器上成功發(fā)布了helloapp 應用后,訪(fǎng)問(wèn)
http://localhost:8080/helloapp/hello.jsp會(huì )看到如圖2-5所示的網(wǎng)頁(yè)。服務(wù)器端裝載hello.jsp網(wǎng)頁(yè)的流程如下。
(1)<bean:message>標簽從Resource Bundle中讀取文本,把它輸出到網(wǎng)頁(yè)上。
(2)<html:form>標簽在request范圍中查找HelloForm Bean。如果存在這樣的實(shí)例,
就把HelloForm對象中的userName屬性賦值給HTML表單的userName文本框。由于此時(shí)
還不存在HelloForm對象,所以忽略這項操作。
(3)把hello.jsp的視圖呈現給客戶(hù)。
圖2-5 直接訪(fǎng)問(wèn)hello.jsp的輸出網(wǎng)頁(yè)
2.8.2 表單驗證的流程
在hello.jsp 網(wǎng)頁(yè)上,不輸入姓名,直接單擊【Submit】按鈕,會(huì )看到如圖2-6 所示的
網(wǎng)頁(yè)。
圖2-6 表單驗證失敗的hello.jsp網(wǎng)頁(yè)
當客戶(hù)提交HelloForm表單時(shí),請求路徑為“/HelloWorld.do”:
<html:form action="/HelloWorld.do" focus="userName" >
服務(wù)器端執行表單驗證流程如下。
PDF 文件使用 "pdfFactory" 試用版本創(chuàng )建
www.fineprint.com.cn精通Struts:基于MVC的Java Web設計與開(kāi)發(fā)
38
(1)Servlet容器在web.xml文件中尋找<url-pattern>屬性為“*.do”的<servlet-mapping>
元素:
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
(2)Servlet 容器依據以上<servlet-mapping>元素的<servlet-name>屬性“action”,在
web.xml文件中尋找匹配的<servlet>元素:
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
</servlet>
(3)Servlet 容器把請求轉發(fā)給以上<servlet>元素指定的ActionServlet,ActionServlet
依據用戶(hù)請求路徑“/HelloWorld.do”,在Struts配置文件中檢索path屬性為“/HelloWorld”
的<action>元素:
<action path = "/HelloWorld"
type = "hello.HelloAction"
name = "HelloForm"
scope = "request"
validate = "true"
input = "/hello.jsp"
>
<forward name="SayHello" path="/hello.jsp" />
</action>
更確切地說(shuō),ActionServlet 此時(shí)檢索的是ActionMapping 對象,而不
是直接訪(fǎng)問(wèn)Struts配置文件中的<action>元素。因為在A(yíng)ctionServlet初始化
的時(shí)候,會(huì )加載Struts 配置文件,把各種配置信息保存在相應的配置類(lèi)的
實(shí)例中,例如<action>元素的配置信息存放在A(yíng)ctionMapping對象中。
(4)ActionServlet根據<action>元素的name屬性,創(chuàng )建一個(gè)HelloForm對象,把客戶(hù)
提交的表單數據傳給HelloForm對象,再把HelloForm對象保存在<action>元素的scope屬
性指定的request范圍內。
(5)由于<action>元素的validate 屬性為true,ActionServlet 調用HelloForm 對象的
validate()方法執行表單驗證:
public ActionErrors validate(ActionMapping mapping,
HttpServletRequest request) {
ActionErrors errors = new ActionErrors();
PDF 文件使用 "pdfFactory" 試用版本創(chuàng )建
www.fineprint.com.cn第2 章 第一個(gè)Struts應用:helloapp應用
39
if ((userName == null) || (userName.length() < 1))
errors.add("username", new ActionMessage("hello.no.username.error"));
return errors;
}
(6)HelloForm 對象的validate()方法返回一個(gè)ActionErrors 對象,里面包含一個(gè)
ActionMessage 對象,這個(gè)ActionMessage 對象中封裝了錯誤消息,消息key 為
“hello.no.username.error”,在Resource Bundle中與值匹配的消息文本為:
hello.no.username.error=Please enter a <i>UserName</i> to say hello to!
(7)ActionServlet 把HelloForm 的validate()方法返回的ActionErrors 對象保存在
request范圍內,然后根據<action>元素的input屬性,把客戶(hù)請求轉發(fā)給hello.jsp。
(8)hello.jsp 的<html:errors>標簽從request 范圍內讀取ActionErrors 對象,再從
ActionErrors對象中讀取ActionMessage對象,把它包含的錯誤消息顯示在網(wǎng)頁(yè)上。
2.8.3 邏輯驗證失敗的流程
接下來(lái)在hello.jsp 的HTML 表單中輸入姓名“Monster”,然后單擊【Submit】按鈕。
當服務(wù)器端響應客戶(hù)請求時(shí),驗證流程如下。
(1)重復2.8.2 小節的流程(1)~(4)。
(2)ActionServlet 調用HelloForm 對象的validate()方法,這次validate()方法返回的
ActionErrors對象中不包含任何ActionMessage對象,表示表單驗證成功。
(3)ActionServlet 查找HelloAction 實(shí)例是否存在,如果不存在就創(chuàng )建一個(gè)實(shí)例。然
后調用HelloAction的execute()方法。
(4)HelloAction 的execute()方法先進(jìn)行邏輯驗證,由于沒(méi)有通過(guò)邏輯驗證,就創(chuàng )建
一個(gè)ActionMessage 對象,這個(gè)ActionMessage 對象封裝了錯誤消息,消息key 為
“hello.dont.talk.to.monster”,在Resource Bundle中與值匹配的消息文本為:
hello.dont.talk.to.monster=We don‘t want to say hello to Monster!!!
execute()方法把ActionMessage 對象保存在A(yíng)ctionMessages 對象中,再把
ActionMessages 對象存放在request 范圍內。最后返回一個(gè)ActionForward 對象,該對象包
含的請求轉發(fā)路徑為<action>元素的input屬性指定的hello.jsp。
以下是execute()方法中進(jìn)行邏輯驗證的代碼:
ActionMessages errors = new ActionMessages();
String userName = (String)((HelloForm) form).getUserName();
String badUserName = "Monster";
if (userName.equalsIgnoreCase(badUserName)) {
PDF 文件使用 "pdfFactory" 試用版本創(chuàng )建
www.fineprint.com.cn精通Struts:基于MVC的Java Web設計與開(kāi)發(fā)
40
errors.add("username", new ActionMessage("hello.dont.talk.to.monster", badUserName ));
saveErrors(request, errors);
return (new ActionForward(mapping.getInput()));
}
(5)ActionServlet 依據HelloAction 返回的ActionForward 對象,再把請求轉發(fā)給
hello.jsp。
(6)hello.jsp 的<html:errors>標簽從request 范圍內讀取ActionMessages 對象,再從
ActionMessages 對象中讀取ActionMessage對象,把它包含的錯誤消息顯示在網(wǎng)頁(yè)上,如圖
2-7所示。
圖2-7 邏輯驗證失敗時(shí)的hello.jsp網(wǎng)頁(yè)
2.8.4 邏輯驗證成功的流程
接下來(lái),在hello.jsp的HTML表單中輸入姓名“Weiqin”,然后單擊【Submit】按鈕。
當服務(wù)器端響應客戶(hù)請求時(shí),流程如下。
(1)重復2.8.3 節的流程(1)~(3)。
(2)HelloAction 的execute()方法先執行邏輯驗證,這次通過(guò)了驗證,然后執行相關(guān)
的業(yè)務(wù)邏輯,最后調用ActionMapping.findForward()方法,參數為“SayHello”:
// Forward control to the specified success URI
return (mapping.findForward("SayHello"));
(3)ActionMapping.findForward()方法從<action>元素中尋找name屬性為“SayHello”
的<forward>子元素,然后返回與之對應的ActionForward 對象,它代表的請求轉發(fā)路徑為
“/hello.jsp”。
更確切地說(shuō),ActionMapping 從本身包含的HashMap 中查找name 屬
性為“SayHello”的ActionForward對象。在A(yíng)ctionServlet初始化時(shí)會(huì )加載
Struts配置文件,把<action>元素的配置信息存放在A(yíng)ctionMapping對象中。
<action>元素中可以包含多個(gè)<forward>子元素,每個(gè)<forward>子元素的配
PDF 文件使用 "pdfFactory" 試用版本創(chuàng )建
www.fineprint.com.cn第2 章 第一個(gè)Struts應用:helloapp應用
41
置信息存放在一個(gè)ActionForward對象中,這些ActionForward對象存放在
ActionMapping對象的HashMap中。
(4)HelloAction 的execute()方法然后把ActionForward 對象返回給ActionServlet,
ActionServlet再把客戶(hù)請求轉發(fā)給hello.jsp。
(5)hello.jsp的<bean:message>標簽從Resource Bundle中讀取文本,把它們輸出到網(wǎng)
頁(yè)上,最后生成動(dòng)態(tài)網(wǎng)頁(yè),如圖2-8所示。
圖2-8 通過(guò)數據驗證的hello.jsp網(wǎng)頁(yè)
2.9 小 結
本章通過(guò)簡(jiǎn)單但完整的helloapp應用的例子,演示了如何把Struts框架運用到Web 應
用的開(kāi)發(fā)中。通過(guò)這個(gè)例子,讀者可以掌握以下內容:
l 分析應用需求,把應用分解為模型、視圖和控制器來(lái)實(shí)現這些需求。
l 利用Struts 的標簽庫來(lái)創(chuàng )建視圖組件。視圖組件中的文本內容保存在專(zhuān)門(mén)的消息
資源文件中,在JSP文件中通過(guò)Struts的<bean:message>標簽來(lái)訪(fǎng)問(wèn)它,這樣可以
很方便地實(shí)現Struts應用的國際化,支持多國語(yǔ)言。
l Struts 框架采用ActionForm Bean 把視圖中的表單數據傳給控制器組件。
ActionForm Bean 被存放在request 或session 范圍內,它能夠被JSP 組件、Struts
標簽以及Action類(lèi)共享。
l 數據驗證分為兩種類(lèi)型:HTML表單驗證和業(yè)務(wù)邏輯驗證。表單驗證由ActionForm
Bean的validate()方法來(lái)實(shí)現。業(yè)務(wù)邏輯驗證由Action類(lèi)或模型組件來(lái)實(shí)現。
l ActionMessage 可以表示數據驗證錯誤,它被保存在A(yíng)ctionMessages(或其子類(lèi)
ActionErrors)集合對象中。ActionMessages 對象被保存在request 范圍內,Struts
的視圖組件可以通過(guò)<html:errors>標簽來(lái)訪(fǎng)問(wèn)它。
l Action 類(lèi)的execute()方法調用模型組件來(lái)完成業(yè)務(wù)邏輯,它還能決定把客戶(hù)請求
轉發(fā)給哪個(gè)視圖組件。
l 模型組件具有封裝業(yè)務(wù)實(shí)現細節的功能,開(kāi)發(fā)者可以方便地把模型組件移植到遠
PDF 文件使用 "pdfFactory" 試用版本創(chuàng )建
www.fineprint.com.cn精通Struts:基于MVC的Java Web設計與開(kāi)發(fā)
42
程應用服務(wù)器上,這不會(huì )對MVC的其他模塊造成影響。
l 通過(guò)調用HttpServletRequest或HttpSession的setAttribute()以及getAttribute()方法,
可以保存或訪(fǎng)問(wèn)在request或session范圍內的Java 對象,從而實(shí)現視圖組件和控
制器組件之間信息的交互與共享。
l 利用struts-config.xml文件來(lái)配置Struts應用。
PDF 文件使用 "pdfFactory" 試用版本創(chuàng )建
www.fineprint.com.cn