Struts controller基本功能是:
1. 截獲用戶(hù)的Http請(qǐng)求
2. 把這個(gè)請(qǐng)求映射到相應(yīng)的Action類(lèi),如果這是此類(lèi)收到的第一個(gè)請(qǐng)求,將初始化實(shí)例并緩存。
3. 創(chuàng)建或發(fā)現(xiàn)一個(gè)ActionForm bean實(shí)例(看配置文件是否定義),然后將請(qǐng)求過(guò)程移植到bean,填充所需的各個(gè)參數(shù)。
4. 調(diào)用Action實(shí)例的perform()方法并將ActioForm bean,Action Mapping對(duì)象,request和response對(duì)象傳給它。
如:public ActionForword perform(ActionMapping mapping, ActionForm form,HttpServletRequest request,HttpServletResponse response)
5.perform返回一個(gè)ActionForword對(duì)象,此對(duì)象連接到相應(yīng)的jsp 。
6.? ActionForward 出來(lái)后,還是交給 ActionServlet ,form / request 還在。只要沒(méi)有 response ,request 還可以由 ActionServlet 轉(zhuǎn)交給別的 aciton 而做別的事情。
ActionServlet使用ActionForm bean來(lái)保存請(qǐng)求的參數(shù),這些bean的屬性名稱(chēng)與HTTP請(qǐng)求參數(shù)的名稱(chēng)相對(duì)應(yīng),控制器將請(qǐng)求參數(shù)傳遞到ActionForm bean的實(shí)例,然后將這個(gè)實(shí)例傳送到Action類(lèi)。
????? 典型的ActionFrom bean只有屬性的設(shè)置與讀取方法(getXXX),而沒(méi)有實(shí)現(xiàn)事務(wù)邏輯的方法。只有簡(jiǎn)單的輸入檢查邏輯,使用的目的是為了存儲(chǔ)用戶(hù)在相關(guān)表單中輸入的最新數(shù)據(jù),以便可以將同一網(wǎng)頁(yè)進(jìn)行再生,同時(shí)提供一組錯(cuò)誤信息,這樣就可以讓用戶(hù)修改不正確的輸入數(shù)據(jù)。而真正對(duì)數(shù)據(jù)有效性進(jìn)行檢查的是ACTION類(lèi)或適當(dāng)?shù)氖聞?wù)邏輯bean。
有幾個(gè)部分共同組成了Struts 的Controller,用戶(hù)的請(qǐng)求發(fā)送到ActionServlet中,ActionServlet調(diào)用RequestProssor開(kāi)始處理用戶(hù)請(qǐng)求的流程,在這個(gè)流程中,會(huì)查找ApplicationConfig,得到用戶(hù)請(qǐng)求對(duì)應(yīng)的Action,調(diào)用相應(yīng)的Action來(lái)具體執(zhí)行用戶(hù)的請(qǐng)求,最后返回ActionForward,轉(zhuǎn)向相應(yīng)的流程。
??????? org.apache.struts.action.ActionServlet? 是Struts Controller中最主要的部分,所有用戶(hù)請(qǐng)求都會(huì)被發(fā)送到這里,所有的其它處理也必須從這里經(jīng)過(guò)。它是從 HttpServlet中繼承過(guò)來(lái)的, 當(dāng)它接收到HTTP request的時(shí)候,不管是doGet()或者doPost()方法,都會(huì)調(diào)用process()方法。
protected void process(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{ RequestUtils.selectApplication( request, getServletContext() );?
getApplicationConfig(request).getProcessor().process( request, response );
}
??????? 一般情況下,我們不需要自己實(shí)現(xiàn)或者修改ActionServlet類(lèi),僅僅使用就可以了。某些情況下,我們可以自己擴(kuò)展 ActionServlet類(lèi),從ActionServlet繼承,實(shí)現(xiàn)自己的MyActionServlet類(lèi)。覆蓋其中的一些方法來(lái)達(dá)到你的特殊處理的需要。
?????? ActionServlet繼承自javax.servlet.http.HttpServlet,所以在本質(zhì)上它和一個(gè)普通的servlet沒(méi)有區(qū)別,你完全可以把它當(dāng)做一個(gè)servlet來(lái)看待,只是在其中完成的功能不同罷了。
??????? RequestProssor具體處理用戶(hù)的request,作為一個(gè)request handler存在。同樣,處理request的時(shí)候,會(huì)執(zhí)行RequestProcessor類(lèi)中的process(execute)方法。
????? process 中調(diào)用的方法都是可以重載的,如果有需要,可以實(shí)現(xiàn)為自己特定的方法。比如,對(duì)于Locale問(wèn)題,通常都是在系統(tǒng)最一開(kāi)始加載的時(shí)候讀取的,如果用戶(hù)想在任何時(shí)刻都可以切換或者選擇自己的Locale,我們就可以重載processLocale()方法。然后只需要在配置文件中加入段就可以了
??????? Action 類(lèi)是實(shí)現(xiàn)整個(gè)體系的核心部分,它在客戶(hù)請(qǐng)求、界面表示和業(yè)務(wù)邏輯之間起到一個(gè)橋梁的作用。每一個(gè)Action都用來(lái)處理某一項(xiàng)任務(wù),或者進(jìn)行一個(gè)業(yè)務(wù)操作。當(dāng)然了,我們說(shuō)一項(xiàng)任務(wù)不是說(shuō)Action只實(shí)現(xiàn)一個(gè)業(yè)務(wù)操作方法,而是集中實(shí)現(xiàn)某一個(gè)功能單元。比如登錄用的LogonAction、查找用的 SearchAction等等。Action是在RequestProcessor中,由processActionPerform方法調(diào)用的
????? 非常重要的一點(diǎn):不要在Action中包含任何業(yè)務(wù)邏輯操作,而是應(yīng)該調(diào)用一個(gè)Model層的JavaBean來(lái)實(shí)現(xiàn)你的業(yè)務(wù)邏輯操作。在某些情況下,可能包含少許表現(xiàn)邏輯。這樣,就可以充分進(jìn)行代碼重用,比如上例中調(diào)用的IStorefrontService接口,這個(gè)接口在實(shí)現(xiàn)時(shí)完全可以不用考慮客戶(hù)端的事情,所以它可以被其它部分或者其它系統(tǒng)所使用。否則的話(huà),Action會(huì)變得非常難于理解,難于維護(hù),代碼也不能重用。
?????? struts-example工程的設(shè)計(jì)就是一個(gè)bug,它把業(yè)務(wù)邏輯封裝到了Action類(lèi)中
????? 在Action 的execute方法中,返回一個(gè)ActionForward類(lèi)。
?????? ActionForward把配置文件中forward部分的信息包裝起來(lái),減少了應(yīng)用程序和物理資源信息之間的耦合性。通過(guò)ActionMapping類(lèi),可以在配置文件中查找相應(yīng)的forward信息。例如,對(duì)于一個(gè) LoginAction它的配置信息可能是這樣的:
???? 返回的ActionForward就會(huì)包含段中的信息。在ActionMapping類(lèi)的findForward方法中,首先會(huì)根據(jù)查找forward的name查找是否有相應(yīng)的forward段,如果沒(méi)有,則在配置文件中的段中進(jìn)行查找,如果還沒(méi)有就會(huì)拋出一個(gè)例外。
??????? 以前,頁(yè)面上的輸入數(shù)據(jù)都通過(guò)HTTP request提交,服務(wù)方檢索出輸入的數(shù)據(jù),進(jìn)行驗(yàn)證,然后將這些數(shù)據(jù)傳遞給其它組件進(jìn)行業(yè)務(wù)處理。一切基本都需要手工編寫(xiě)代碼進(jìn)行操作,比較麻煩,也使代碼變得復(fù)雜。
?????? ActionForm[org.apache.struts.action.ActionForm]用來(lái)收集用戶(hù)的輸入,并且把這些信息傳遞給Action對(duì)象,然后,在Action對(duì)象中,ActionForm中的數(shù)據(jù)被取出來(lái)傳遞給業(yè)務(wù)邏輯層進(jìn)行處理。
ActionForm一方面作為一個(gè)緩沖區(qū),臨時(shí)存儲(chǔ)用戶(hù)輸入的數(shù)據(jù);另一方面,可以把ActionForm當(dāng)成是HTTP和Action之間的一個(gè)防火墻,它可以驗(yàn)證輸入數(shù)據(jù)的正確性,如果驗(yàn)證不通過(guò),這個(gè)request是不會(huì)發(fā)送給Action進(jìn)行處理的。
??????? ActionForm可以有兩種Scope,request或者session。request就是只能在rquest到response,之后ActionForm就不可見(jiàn)了;session可以保存時(shí)間長(zhǎng)一點(diǎn)。
?????? 在ActionForm的Validate方法中返回的是ActionErrors對(duì)象。這個(gè)對(duì)象可以將錯(cuò)誤信息都封裝起來(lái),并且自動(dòng)把它們顯示給用戶(hù)。
?????? 在相應(yīng)JSP頁(yè)面上添加,可以自動(dòng)將ActionErrors中的錯(cuò)誤信息顯示出來(lái)。包括,每一個(gè)具體的,通過(guò)add添加的錯(cuò)誤信息,和一個(gè)ErrorHeader和一個(gè)ErrorFooter,這些都可以通過(guò)配置文件指定,并且可以包含HTML語(yǔ)法。
Struts提供了四種自定義Tag庫(kù):
bean:struts-bean taglib包含在訪(fǎng)問(wèn)bean和bean屬性時(shí)使用的tag,也包含一些消息顯示的tag。
html:struts-html taglib包含用來(lái)創(chuàng)建struts輸入表單的tag,和其它通常用來(lái)創(chuàng)建基于HTML用戶(hù)界面的tag。
logic:struts-logic taglib包含的tag用來(lái)管理根據(jù)條件生成輸出文本,和其它一些用來(lái)控制的信息。
template:struts-template taglib包含的tag用來(lái)定義模板機(jī)制。
以下是一個(gè)范例:
reguser.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" %>
<html:html locale="true">
<head>
<title>RegUser</title>
<html:base/>
</head>
<body bgcolor="white">
<html:errors/>
<html:form action="/regUserAction" focus="logname">
<table border="0" width="100%">
? <tr>
??? <th align="right">
????? Logname:
??? </th>
??? <td align="left">
????? <html:text property="logname" size="20" maxlength="20"/>
??? </td>
? </tr>
? <tr>
??? <th align="right">
????? Password:
??? </th>
??? <td align="left">
????? <html:password property="password" size="20" maxlength="20"/>
??? </td>
? </tr>
? <tr>
??? <th align="right">
????? E-mail:
??? </th>
??? <td align="left">
????? <html:password property="email" size="30" maxlength="50"/>
??? </td>
? </tr>
? <tr>
struts-config.xml:
<Struts-config>
<form-beans>
<form-bean????? name="regUserForm"
type="org.cjea.Struts.example. RegUserForm "/>
</form-beans>
<action-mappings>
<action? path="/regUserAction"
??????? type=" org.cjea.Struts.example.RegUserAction "
??????? attribute=" regUserForm "
??????? scope="request"
??????? validate="false">
????? <forward name="failure"?? path="/ messageFailure.jsp"/>
????? <forward name="success"? path="/ messageSuccess.jsp"/>
</action>
</action-mappings>
</Struts-config>
RegUserForm:
import javax.Servlet.http.HttpServletRequest;
import org.apache.Struts.action.ActionForm;
import org.apache.Struts.action.ActionMapping;
public final class RegUserForm extends ActionForm{
? private String logname;
? private String password;
? private String email;
? public RegUserForm(){
??? logname = null;
??? password = null;
??? email = null;
? }
? public String getLogName() {
??? return this.logname;
? }
? public void setLogName(String logname) {
??? this.logname = logname;
? }
? public void setPassWord(String password) {
??? this.password = password;
? }
? public String getPassWord() {
??? return this.password;
? }
? public void setEmail(String email) {
??? this.email = email;
? }
? public String getEmail() {
??? return this.email;
? }
? public void reset(ActionMapping mapping, HttpServletRequest request)
??? {
??????? logname = null;
??????? password = null;
??????? email = null;
??? }
}
RegUserAction :
import javax.Servlet.http.*;
import org.apache.Struts.action.*;
public final class RegUserAction extends Action
{
public ActionForward perform(ActionMapping mapping,
? ActionForm form,? HttpServletRequest req,
? HttpServletResponse res)
{?
? String title = req.getParameter("title");
? String password = req.getParameter("password");
? String email = req.getParameter("email");
? }
}
文章來(lái)源:http://x-spirit.spaces.live.com/Blog/cns!CC0B04AE126337C0!373.entry