




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
第5章Struts2框架基礎(chǔ)5.1Struts2注冊功能的實現(xiàn)5.2struts.xml配置詳解5.3增加模型組件與權(quán)限分離的方法
5.1Struts2注冊功能的實現(xiàn)
5.1.1Struts2框架在Web應(yīng)用中的環(huán)境搭建
【步驟1】下載Struts2使用的相關(guān)Jar包。
登錄/download.cgi站點,查找所需版本,一般下載完整版,即FullDistribution;然后將下載的Zip文件解壓縮。以下為struts-2.0.14-all.zip解壓后包含的文件結(jié)構(gòu):
apps:包含基于Struts2框架的示例應(yīng)用,可以直接部署到服務(wù)器上運行;
docs:包含所有Struts2框架的相關(guān)文檔;
lib:包含Struts2框架的核心類庫,以及其所依賴的第三方插件類庫;
src:包含Struts2框架的所有源代碼(開源)。
【步驟2】把Web應(yīng)用需要的Jar包配置到項目中。
配置一個基本的Struts2應(yīng)用至少包含以下Jar包:
freemaker-2.3.8.jar:Struts2的UI標簽?zāi)0迨褂肍reeMaker編寫;
ognl-2.6.11.jar:對象圖導航語言,Struts2使用的一種表達式語言;
struts2-core-2.0.14.jar:Struts2的核心類庫;
xwork-2.0.7.jar:Struts2在XWork類庫上構(gòu)建;
commons-logging-1.0.4.jar:Struts2日志包。它們來自Struts2解壓縮包的Lib文件夾。每個基于Struts2框架的應(yīng)用都要先提供所需要的Jar包。
按第4章的講解,建立Web工程ch05并將以上的5個Jar文件復制到工程的WEB-INF/lib路徑下,則這些包會自動配置到環(huán)境變量中,如圖5-1所示。圖5-1Jar包的導入若看不到【ReferencedLibraries】中的內(nèi)容,可以選中工程并點擊右鍵,在彈出的快捷菜單中選擇【BuildPath】中的【ConfigBuildPath】,將打開如圖5-2所示的界面,則說明導入成功。圖5-2Libraries目錄
【步驟3】配置web.xml文件。
打開工程中如圖5-1所示的WEB-INF/web.xml文件,增加Struts2的核心Filter配置,代碼片段如下:
<?xmlversion="1.0"encoding="UTF-8"?>
<web-appversion="2.4"
xmlns="/xml/ns/j2ee"
xmlns:xsi="/2001/XMLSchema-instance"
xsi:schemaLocation="/xml/ns/j2ee
/xml/ns/j2ee/web-app_2_4.xsd">
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>5.1.2視圖表單頁面
Struts2支持大部分視圖技術(shù),當然也支持最傳統(tǒng)的JSP視圖技術(shù)。
以下Struts2標簽實現(xiàn)登錄表單提交和顯示功能。登錄信息包括兩個表單域:用戶名(username)和密碼(password)。
1.登錄表單請求頁面
【步驟1】建立login.jsp文件。
使用第4章講解的方法在ch05中新建login.jsp文件,注意文件的放置目錄為ch05/WebRoot。在login.jsp頁面的【Design】視圖中把JSP頁面的pageEncoding屬性修改為“gb2312”(第一行),同時加入struts標簽導入語句(第二行),代碼如下:
<%@taglibprefix="s"uri="/struts-tags"%>頁面代碼如下:
<%@pagelanguage="java"import="java.util.*"
pageEncoding="gb2312"%>
<%@taglibprefix="s"uri="/struts-tags"%>
……
<body>
<s:formaction="loginAction">
<s:textfieldname="username"label="username">
</s:textfield>
<s:passwordname="password"
label="password"></s:password>
<s:submitname=“submit”></s:submit>
</s:form>
</body>
【步驟2】運行注冊頁面。
用第4章講解的方法在MyEclipse中部署ch05工程,并啟動Tomcat,運行工程http://localhost/ch05/,顯示如圖5-3所示的界面。讀者在今后的學習中也可用此方法來避免文件名的錯誤輸入。圖5-3ch05工程運行界面點擊login.jsp的超鏈接,顯示表單如圖5-4所示。
圖5-4登錄表單頁面圖
2.注冊表單響應(yīng)頁面
同請求頁面生成一樣,新建loginok.jsp,僅把【步驟1】的代碼換成如下代碼:
<%@pagelanguage="java"import="java.util.*"
pageEncoding="gb2312"%>
<%@taglibprefix="s"uri="/struts-tags"%>
……
<body>
歡迎<s:propertyvalue="username"/>??!
</body>由于尚未配置Struts2控制器,注冊響應(yīng)界面無值傳入,因此運行界面如圖5-5所示。圖5-5登錄響應(yīng)頁面
3.?Struts2標簽簡介
1)標簽庫的導入
Struts2標簽庫的描述文件包含在Struts2的核心JAR包(struts2-core-2.0.14.jar)中,在META-INF目錄下,文件名為struts-tags.tld。
JSP2.0規(guī)范中規(guī)定,標簽庫部署在JAR包中時,標簽庫描述符文件必須放在META-INF目錄或其子目錄下,放在META-INF目錄下的TLD文件會被容器自動加載。在struts-tags.tld文件中,設(shè)置了<uri>元素,如下所示:
<uri>/struts-tags</uri>
在JSP頁面中引用Struts2標簽庫時,需要使用taglib指令,該指令的uri屬性的值設(shè)為這里的<uri>元素的內(nèi)容。至于prefix屬性,通常設(shè)為“s”,如上面jsp頁面的設(shè)置。
<%@taglibprefix="s"uri="/struts-tags"%>
2)?form標簽
Struts2的表單標簽可以分為兩類:form標簽本身和包裝HTML表單元素的其他標簽。下面先介紹form標簽。
form標簽常用的屬性如表5-1所示。
3)表單元素的其他標簽
登錄功能的表單填寫頁面用到兩個表單標簽:textfield和password。這兩個標簽相當于HTML表單標簽中的text和password標簽。這兩個標簽常用的屬性如表5-2所示。
4)數(shù)據(jù)標簽property
在上面的loginok.jsp中使用了property標簽,很明顯,property標簽用于輸出值棧中的對象屬性值,使用value屬性來指定要輸出的對象屬性。property標簽常用的屬性如表5-3所示。
4.注冊頁面的純JSP實現(xiàn)下面提供以上Struts2實現(xiàn)表單的純JSP編碼,讓讀者用熟悉的語言來對照Struts2標簽的功效。
login_jsp.jsp代碼如下:
<body>
<formaction="loginAction.action">
<tableborder="0"><tr>
<td>username</td>
<td><inputtype="text"name="username"/></td></tr>
<tr><td>password</td>
<td><inputtype="password"name="password"/>
</td></tr>
<tr><td><inputtype="submit"value="submit"/></td>
<td></td></tr>
</table>
</form>
</body>
loginok_jsp.jsp代碼如下:
<body>
歡迎<%=request.getParameter("username")%>??!
</body>當表單提交loginAction.action時,Struts2的FilterDispatcher將自動起作用,將用戶請求轉(zhuǎn)發(fā)到對應(yīng)的Struts2Action,Struts2Action默認攔截所有后綴為.action的請求。在Struts2中,struts2-core-2.0.14.jar包中的org.apache.struts2包中有個perties文件,它定義了Struts2Action默認攔截的請求后綴。5.1.3控制器類的實現(xiàn)
1.代碼實現(xiàn)
下面就是建立Struts2控制器類的步驟:
【步驟1】建立控制器類com.action.LoginAction.java。
在ch05工程的src目錄下,右鍵單擊【New】的【Class】子菜單,填寫如圖5-6所示的頁面,新建com.action包中的Action文件LoginAction.java,并實現(xiàn)Action接口。圖5-6新建控制器類
【步驟2】初步完成表單屬性和execute方法。
在新建的LoginAction.java文件中輸入如下代碼:
packagecom.action;
importcom.opensymphony.xwork2.Action;
publicclassLoginActionimplementsAction{
privateStringusername;
privateStringpassword;
publicStringexecute()throwsException{
returnSUCCESS;
}
}
【步驟3】生成屬性的get/set方法。
在文件中要插入屬性的get/set方法處點擊鼠標右鍵,選擇【Source】的【GenerateGettersandSetters】,在出現(xiàn)的如圖5-7所示的界面中選中所有屬性。圖5-7get/set方法產(chǎn)生器點擊【OK】按鈕,則會自動產(chǎn)生如下代碼:
publicStringgetUsername(){
returnusername;}
publicvoidsetUsername(Stringusername){
this.username=username;}
publicStringgetPassword(){
returnpassword;}
publicvoidsetPassword(Stringpassword){
this.password=password;
}
2.實現(xiàn)原理
Struts2的Action接口里定義了五個常量,一個execute方法。這五個常量就是在日常開發(fā)中業(yè)務(wù)邏輯方法返回的字符串,execute方法則是Action接口定義的一個默認的業(yè)務(wù)邏輯方法。五個常量分別代表特定的含義:●?SUCCESS:表示請求處理成功;
●?ERROR:表示請求處理失??;
●?NONE:表示請求處理完成后不跳轉(zhuǎn)到任何頁面;
●?INPUT:表示輸入時如果驗證失敗應(yīng)該跳轉(zhuǎn)到什么地方;
●?LOGIN:表示登錄失敗后跳轉(zhuǎn)的目標。
這些常量可以簡化和標準化execute方法的返回值,避免直接返回字符串,但是如果有特殊返回意義,則還可以自定義字符串。5.1.4struts.xml配置的實現(xiàn)
與大部分Java框架類似,Struts2框架也采用XML配置文件來管理Struts2資源。Struts2默認配置文件名為struts.xml,該文件要求放在Web應(yīng)用的類加載路徑下,通常放在WEB-INF/classes路徑下。struts.xml配置文件最大的作用就是配置Action和請求之間的對應(yīng)關(guān)系,并配置邏輯視圖名和物理視圖資源之間的對應(yīng)關(guān)系。
【步驟1】創(chuàng)建struts.xml文件。
由于MyEclipse的IDE會自動把src目錄下的文件編譯到WEB-INF/classes文件中,所以只要在ch05工程的src文件夾根目錄下建立struts.xml文件即可。右擊src文件夾,選擇【New】菜單下的【XML(BasicTemplates)】,在彈出的圖5-8中把文件名改成struts.xml,直接點擊【Finish】即可。圖5-8生成struts.xml文件
【步驟2】完成struts.xml的文檔類型聲明。
struts.xml和Struts2核心包(struts2-core-2.0.14.jar)中的struts-default.xml文件的結(jié)構(gòu)是一樣的,都是由struts-2.0.dtd來定義的。struts-default.xml給出了適合大多數(shù)Web應(yīng)用程序的基本配置,而struts.xml通常從struts-default.xml中繼承默認的包定義,并給出特定Web應(yīng)用程序的action配置。所以,我們可以打開struts-default.xml,把它的DTD申明拷貝過來,代碼如下:
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPEstrutsPUBLIC
"-//ApacheSoftwareFoundation//DTDStrutsConfiguration2.0//EN"
"/dtds/struts-2.0.dtd">
【步驟3】完成registerAction轉(zhuǎn)發(fā)的配置。
<struts>
<constantname="struts.i18n.encoding"value="gbk"></constant>
<packagename="struts2"extends="struts-default"namespace="">
<actionname="loginAction"class="com.action.LoginAction">
<resultname="input">/login.jsp</result>
<resultname="success">/loginok.jsp</result>
</action>
</package>
</struts>
【步驟4】項目運行
完成配置后可以運行本項目。啟動服務(wù)器,在IE中輸入地址http://localhost/ch05/login.jsp,將顯示如圖5-9所示的界面。填好信息后,點擊【submit】,將進入如圖5-10所示的界面。注意,此時地址欄的名字為http://localhost/ch05/loginAction.action,但界面內(nèi)容卻是loginok.jsp,說明struts.xml的配置起作用了。
圖5-9運行輸入界面圖5-10提交轉(zhuǎn)入頁面對于整個登錄的處理流程,可以簡化如下:用戶輸入兩個參數(shù)username和password,然后向login.action發(fā)送請求,該請求被FilterDispatcher轉(zhuǎn)發(fā)給LoginAction處理。如果LoginAction處理用戶請求后返回success,則返回給用戶loginok.jsp頁面;如果輸入錯誤,則系統(tǒng)默認返回login.jsp頁面,并要求重新輸入。5.1.5Struts2框架的工作流程
Struts2框架按照模塊,可以分為ServletFilters、Struts核心模塊、攔截器和用戶實現(xiàn)部分。Struts2官方站點提供的Struts2的整體結(jié)構(gòu)如圖5-11所示。圖5-11Struts2結(jié)構(gòu)圖一個請求在Struts2框架中的處理大概分為以下幾個步驟:
(1)客戶端提交一個(HttpServletRequest)請求。如上文中提交注冊信息后,在瀏覽器中地址為http://localhost/ch05/loginAction.action,就是提交一個(HttpServletRequest)請求。
(2)請求被提交到一系列(主要是3層)的過濾器(Filter),如ActionContextCleanUp、其他過濾器(SiteMesh等)、FilterDispatcher。注意:這里是有順序的,先ActionContextCleanUp,然后為其他過濾器(OtherFilters、SiteMesh等),最后到FilterDispatcher。
(3)?FilterDispatcher是控制器的核心,就是MVC的Struts2實現(xiàn)中控制層(Controller)的核心。
(4)?FilterDispatcher詢問ActionMapper是否需要調(diào)用某個Action來處理這個(HttpServletRequest)請求,如果ActionMapper決定需要調(diào)用某個Action,F(xiàn)ilterDispatcher則把請求的處理交給ActionProxy。
(5)?ActionProxy通過ConfigurationManager(struts.xml)詢問框架的配置文件,找到需要調(diào)用的Action類。例如,注冊示例將找到LoginAction.java類。
(6)?ActionProxy創(chuàng)建一個ActionInvocation實例,同時ActionInvocation通過代理模式調(diào)用Action。如果在struts.xml文件中配置method參數(shù),則調(diào)用method參數(shù)對應(yīng)的Action類中的method方法,否則調(diào)用通用的execute()方法來處理用戶請求;但在調(diào)用之前,ActionInvocation會根據(jù)配置加載Action相關(guān)的所有Interceptor(攔截器)。
(7)一旦Action執(zhí)行完畢,ActionInvocation負責根據(jù)struts.xml中的配置找到對應(yīng)的返回結(jié)果result。
5.2struts.xml配置詳解
5.2.1struts.xml文件的元素結(jié)構(gòu)
struts.xml文件的元素結(jié)構(gòu)圖如圖5-12所示。
在圖5-12中,星號(*)表示0個或多個元素,問號(?)表示該元素是可選的,加號(+)表示該元素至少有一個或多個,沒有添加這三種符號的元素表明該元素是必需的。圖5-12struts.xml文件的元素結(jié)構(gòu)圖5.2.2包含(include)的配置
在默認情況下,Struts2框架將自動加載放在WEB-INF/classes路徑下的struts.xml文件中。在大部分應(yīng)用里,隨著應(yīng)用規(guī)模的增加,系統(tǒng)中Action的數(shù)量也將大量增加,導致struts.xml配置文件變得非常臃腫。
為了避免struts.xml文件過于龐大,提高struts.xml文件的可讀性,可以將一個struts.xml配置文件分解成多個配置文件,然后在struts.xml文件中包含其他配置文件。<?xmlversion="1.0"encoding="UTF-8"?>
<!--指定Struts2配置文件的DTD信息-->
<!DOCTYPEstrutsPUBLIC
"-//ApacheSoftwareFoundation//DTDStrutsConfiguration2.0//EN"
"/dtds/struts-2.0.dtd">
<!--下面是Struts2配置文件的根元素-->
<struts>
<!--通過include元素導入其他配置文件-->
<includefile="com/action/cart/struts-cart.xml"/>
...
</struts>5.2.3常量(constant)的配置
常量可以在多個文件中聲明,分別為:
①?struts-default.xml;
②?struts-plugin.xml;
③?struts.xml;
④?perties;
⑤?web.xml。
1.?struts.xml配置常量
struts.xml配置常量使用constant標簽,其包含兩個屬性值:name和value。其中,name是常量的名字,如果定義的常量是Struts2內(nèi)置的屬性,如編碼(struts.i18n.encoding)、國際化資源包文件基名(struts.custom.i18n.resources)等,則可以在perties中查找對應(yīng)的常量名;value就是常量的值。
<struts>
<constantname="struts.i18n.encoding"value="gb2312"></constant>
<constantname="struts.custom.i18n.resources"
value="message"></constant>
…
</struts>
2.屬性(properties)文件
perties文件中,每一個鍵-值對就是一個常量
設(shè)置。對于以上的struts.custom.i18n.resources的常量值為message,這表示在Struts2中定義了一個名為perties的屬性文件,此文件必須放在WEB-INF/classes的根目錄下。建立屬性文件的步驟為:
【步驟1】新建文件perties。
選擇src文件夾,右擊【New】下的【File】子菜單,在出現(xiàn)的如圖5-13所示的界面中輸入文件名perties,點擊【Finish】即可。
【步驟2】設(shè)置編碼值。
在打開的perties文件中輸入以下代碼即可。
struts.i18n.encoding=gb2312圖5-13新建屬性文件圖
3.?web.xml配置常量
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
<init-param>
<param-name>struts.i18n.encoding</param-name>
<param-value>gb2312</param-value>
</init-param>
</filter>5.2.4包(package)和名稱空間(namespace)的配置
1.?package配置
Struts2中的包(package)類似于Java中的包,每個包都包含了將要用到的action、result和攔截器的定義。但是和Java中的包不同的是,Struts2的包可以擴展另外的包,從而“繼承”原有包的所有定義,并可添加自己包特有的配置,以及修改原有包的部分配置。struts.xml中的package元素包含的屬性如表5-4所示。在以上屬性中,name的值必須是唯一的,在一個struts.xml中不能出現(xiàn)兩個同名的包。extends屬性允許一個包繼承一個或多個先前定義的包的配置,如果定義多個,則用逗號隔開。在注冊示例的配置中,表示名為struts2的包繼承struts-default包,這個包位于struts-default.xml中,是Struts2框架自動加載的。?<packagename="struts2"extends="struts-default">
…
</package>
<packagename="struts-cart"extends="struts2">
…
</package>
2.?namespace配置
package元素的namespace屬性可以將包中的action配置為不同的名稱空間,這樣在不同名稱空間中可以使用同名action。Struts2框架使用action名字和它所在的名稱空間來標識一個action。而namespace可以不定義,就是默認名稱空間,當請求在自己的名稱空間沒有找到對應(yīng)的action時,就會自動查找默認名稱空間中相同名字的請求,如以下編碼:<packagename="struts2"extends="struts-default">
<actionname="loginAction"class="com.action.LoginAction">
……
</action>
</package>
<packagename="struts-cart"extends="struts-default"namespace="/cart">
<actionname="registerAction"class="com.action.RegisterAction">
……
</action>
</package>當請求/cart/loginAction.action發(fā)生時,Struts2框架首先查找/cart名稱空間的loginAction.action,如果找到了,就執(zhí)行;如果像以上代碼中一樣沒有找到,就會到默認的名稱空間繼續(xù)查找,找到后再執(zhí)行。5.2.5action的配置
Struts的核心是action,通常action類都要實現(xiàn)com.opensymphony.xwork2.Action接口,實現(xiàn)該接口的execute()方法。但在實際開發(fā)中很少直接實現(xiàn)Action接口,而是繼承ActionSupport類(詳解見第6章)。開發(fā)好action后,就要配置action映射,用來通知Struts2框架,針對某個URL的請求應(yīng)該交由哪個action進行處理。
1.?action映射
action映射就是將一個請求URI(即action名字)映射到一個action類,當一個請求匹配某個action名字時,框架就使用這個映射來確定如何處理請求。struts.xml文件中的每一個action元素就是一個action映射。Action元素的完整屬性如表5-5所示。如5.1.4中的配置:
<actionname="
loginAction"
class="
com.action.LoginAction">
<resultname="input">/login.jsp</result>
<resultname="success">/loginok.jsp</result>
</action>
要注意避免以下事項:
■一般不允許出現(xiàn)斜杠(/);
■名字中盡量不要使用點號(.)和連字符(-)。
2.使用method屬性
在業(yè)務(wù)邏輯開發(fā)中,為了節(jié)省action的數(shù)量,通常在一個action類中編寫多個業(yè)務(wù)方法,如數(shù)據(jù)庫的CRUD操作(Create、Read、Update、Delete)。大家到目前也應(yīng)該清楚,在執(zhí)行action時,默認調(diào)用的方法是execute(),那么如何讓不同請求到來時,使用框架去調(diào)用同一個action的不同方
法呢?我們先看以下action代碼片段(來源于5.3節(jié)的示例):
publicclassLoginActionimplementsAction{
publicStringexecute()throwsException{
returnSUCCESS;}
publicStringlogin()throwsException{
…
returnSUCCESS;}
}
LoginAction.java中定義了兩個邏輯方法execute()和login()。注意,login()的結(jié)構(gòu)必須符合execute()的結(jié)構(gòu)publicStringexecute()throwsException{}。那么在配置action時,可以通過method屬性來指定action調(diào)用的方法,見struts.xml片段(來源于5.3節(jié)的示例):<actionname="loginAction"class="com.action.LoginAction">
<resultname="input">/login.jsp</result>
<resultname="success">/loginok.jsp</result>
</action>
<actionname="isUMAction"class="com.action.LoginAction"method="login">
<resultname="input">/login.jsp</result>
<resultname="success">/user.jsp</result>
</action>
3.通配符映射
隨著Web應(yīng)用規(guī)模的增大,Action的數(shù)量會非常龐大,這時可使用通配符映射來減少action配置的數(shù)量。
代碼如下:
<actionname="*Crud"class="example.Crud"
method="{1}">
這里,當在應(yīng)用中將action指定為“editCrud”時,將調(diào)用editCrudAction處理類實例中的edit方法。另外一種方法是通過action的后綴來匹配方法名,并且通過感嘆號、下劃線或者其它特殊字符將其分開,如action="/Crud_input.action"或action="/Crud_delete.action"。下面的代碼片斷演示了在action名稱的最后使用星號通配符的示例:
<actionname="Crud_*"class="example.Crud"method=
"{1}">
當然通配符除了*號外,還有其他內(nèi)容:
*:匹配0個或多個字符,斜杠(/)字符除外;
**:匹配0個或多個字符,包括斜杠(/)字符;
\:反斜杠字符被用作轉(zhuǎn)義序列,例如,\*匹配星號(*),\\匹配反斜杠字符(\)。5.2.6Result的配置
1.結(jié)構(gòu)映射
在struts.xml文件中,使用result元素來配置result映射。result元素的屬性如表5-6所示。
2.常用結(jié)果類型
1)?dispatcher結(jié)果類型
Struts2將dispatcher設(shè)為默認的結(jié)果類型,就像在登錄示例中沒有定義結(jié)果類型,但都默認使用dispatcher轉(zhuǎn)發(fā)。
dispatcher轉(zhuǎn)發(fā)地址中可以使用OGNL表達式(參見第6章),例如在購物車系統(tǒng)中,每個商品都有一個id號來標識,當用戶點擊購買時,此請求一定帶有id號,傳送此id的地址可以寫成:
<result>/cart.jsp?id=${id}</result>
2)?redirect結(jié)果類型
redirect結(jié)果類型相當于使用HttpServletResponse的sendRedirect方法將請求重定向到指定的URL,就是重定向后的URL地址是實際訪問的頁面地址,而不是action的名字。由于這個原因,使用redirect結(jié)果類型可以避免重復提交表單的操作。
3)?redirectAction結(jié)果類型
redirectAction結(jié)果類型和redirect結(jié)果類型的后臺工作原理是一樣的,都是使用HttpServletResponse的sendRedirect方法將請求重定向到指定的URL。但是redirectAction結(jié)果類型主要用于重定向到action。具體示例請參照下面第3點“動態(tài)結(jié)果”的內(nèi)容。
3.動態(tài)結(jié)果
所謂動態(tài)結(jié)果,是指在配置時你不知道要執(zhí)行哪個結(jié)果,在運行時才能確定執(zhí)行的結(jié)果。也就是說,利用表達式來配置結(jié)果,在運行時,框架解析并計算表達式,根據(jù)表達式的值來確定要執(zhí)行的結(jié)果。
例如在登錄功能中,如果一個系統(tǒng)有多個不同的角色管理,那么登錄成功后應(yīng)該進入不同的操作界面,以達到操作權(quán)限的分離。分析下面的代碼片段(來源于5.3節(jié)的示例):
publicclassLoginActionimplementsAction{
……
//用于保存請求重定向到的action名字;
privateStringnextAction;
……
publicStringgetNextAction(){
returnnextAction;}
publicStringlogin()throwsException{
……
if(…){//驗證用戶是否為管理員;
nextAction=“manager”;
}else{
nextAction=“user”;}
returnSUCCESS;
……
}
}
LoginAction在用戶登錄驗證成功后,判斷用戶的權(quán)限,根據(jù)用戶是管理者還是普通用戶來設(shè)置示例變量nextAction的值。
以下是struts.xml文件的代碼片段(來源于5.3節(jié)的示例):
<actionname="isUMAction"class=“com.action.LoginAction"method="login">
<resultname="input">/login.jsp</result>
<resulttype="redirectAction">${nextAction}</result>
</action>
<actionname=“manager”>
<result>/manager.jsp</result>
</action>
<actionname=“user”>
<result>/user.jsp</result>
</action>
使用${nextAction}來獲取Action中的nextAction屬性的值,而這個值要到運行時刻才能確定。
5.3增加模型組件與權(quán)限分離的方法
5.3.1增加虛擬模型
【步驟1】新建模型組件。
在src目錄下新建com.service.ProductService.java文件,此模型中定義了判斷權(quán)限的userOrManager()方法和獲取產(chǎn)品的getProducts()方法。一般Struts2的模型組件就是用來定義各種業(yè)務(wù)邏輯方法的,這樣方便代碼測試。代碼如下:
packagecom.service;
publicclassProductService{
//以一個常量數(shù)組模擬登陸后從數(shù)據(jù)庫中取出的數(shù)據(jù);
privateStringproducts[]=newString[]{"a","a2","b1","b2"};
//業(yè)務(wù)邏輯方法,該方法返回全部產(chǎn)品;
publicString[]getProducts(){
returnproducts;
}
//業(yè)務(wù)邏輯方法,該方法返回0為普通用戶,1為管
理員;
publicintuserOrManager(Stringusername,String
password){
if(“張三”.equals(username)&&
“123456”.equals(password)){return1;
}else{
return0;
}
}
}
【步驟2】修改action文件。
修改action文件com.action.LoginAction.java,增加與execute()方法結(jié)構(gòu)一樣的方法login(),在此方法中把登錄名放進session范圍變量,并根據(jù)登錄權(quán)限設(shè)置登錄成功的action轉(zhuǎn)發(fā)名,另外還可取得模型中的產(chǎn)品變量的數(shù)據(jù)。代碼如下:
packagecom.action;
importjavax.servlet.http.HttpServletRequest;
importorg.apache.struts2.ServletActionContext;
importcom.opensymphony.xwork2.Action;
importcom.opensymphony.xwork2.ActionContext;
importcom.service.ProductService;
publicclassLoginActionimplementsAction{
privateStringusername;
privateStringpassword;
privateStringproducts[];
//用于保存請求重定向到的action名字;
privateStringnextAction;
……//省略username與password的get/set方法
publicvoidsetProducts(String[]products){
ducts=products;}
publicString[]getProducts(){
returnproducts;}
publicStringgetNextAction(){
returnnextAction;}
publicStringexecute()throwsException{
returnSUCCESS;
}
publicStringlogin()throwsException{
ActionContextct=ActionContext.getContext();
HttpServletRequestrequest=
(HttpServletRequest)ct.get(ServletActionContext.
HTTP_REQUEST);
if(getUsername()!=null){
request.getSession().setAttribute(“session_name”,getUsername());
ProductServiceproductService=newProductService();
//判斷是否管理者
if(productService.userOrManager(getUsername(),getPassword())==1){
nextAction="manager";
}else{
nextAction=“user";}
//設(shè)置用戶購買的產(chǎn)品
setProducts(productService.getProducts());
returnSUCCESS;
}else{
returnINPUT;
}}}
【步驟3】修改struts.xml配置。
為了運行action文件中的login()方法,需要對struts.xml文件進行修改,使得登錄成功后管理員轉(zhuǎn)入manager.jsp頁面,用戶轉(zhuǎn)入user.jsp頁面。代碼如下:
<packagename="struts2"extends="struts-default"
namespace="">
<actionname="loginAction"
class="com.action.LoginAction">
<resultname="input">/login.jsp</result>
<resultname="success">/loginok.jsp</result>
</action>
<actionname="isUMAction"
class="com.action.LoginAction"method="
login">
<resultname="input">/login.jsp</result>
<resulttype="redirectAction">${nextAction}</result>
</action>
<actionname="manager">
<result>/manager.jsp</result>
</action>
<actionname="user">
<result>/user.jsp</result>
</action>
</package>
useraction和manageraction沒有指定類名,只是利用Action進行轉(zhuǎn)發(fā),因此默認使用com.opensymphony.xwork2.ActionSupport類。
【步驟4】修改和新增視圖。
(1)修改login.jsp表單。需要把登錄提交的action改為isUMAction.action。代碼如下:
<%@pagelanguage="java"import="java.util.*"
pageEncoding="GB2312"%>
<%@taglibprefix="s"uri="/struts-tags"%>
<body>
<s:formaction="isUMAction">
<s:textfieldname="username"
label="username"></s:textfield>
<s:passwordname="password"
label="password"></s:password>
<s:submitname="submit"></s:submit>
</s:form>
</body>
(2)新增manager.jsp頁面。在manager.jsp中顯示session范圍的變量session_name的值,使用OGNL表單式(見第6章)。代碼如下:
<%@pagelanguage="java"import="java.util.*"
pageEncoding="GB2312"%>
<%@taglibprefix="s"uri="/struts-tags"%>
<body>
歡迎管理員:${sessionScope.session_name}!!
</body>
(3)新增user.jsp頁面。在user.jsp頁面中除了顯示登錄名外,還要顯示用戶購買的商品,其中使用Struts2標簽完成循環(huán)和判斷的操作。代碼如下:
<%@pagelanguage="java"import="java.util.*"
pageEncoding=“GB2312”%>
<%@taglibprefix="s"uri="/struts-tags"%>
<body>
歡迎用戶:${sessionScope.session_name}??!<br>您購買的商品中排在偶數(shù)位的物品清單如下:<br>
<s:iteratorvalue="#ducts"status="index"id="product_index">
<!--判斷序號是否為偶數(shù)-->
<s:iftest="#index.odd==false">
<s:propertyvalue="product_index"/>
</s:if>
<s:else><br></s:else>
</s:iterator>
</body>■?iterator標簽
iterator標簽用于迭代一個集合(包括Collection、Map、Enumeration、Iterator或者array數(shù)組)。iterator標簽在迭代過程中,會把迭代的每一個對象暫時壓入值棧,這樣在標簽內(nèi)部就可以直接訪問對象的屬性和方法,在標簽執(zhí)行完畢后,位于棧頂?shù)膶ο缶蜁粍h除;在第二次迭代過程中,再壓入新的對象。
iterator標簽的屬性如表5-7所示?!?if/else-if/else標簽
if標簽用于基本的流程控制,它可以單獨使用,也可
以和一個或多個else-if標簽,或者和一個else標簽一起使
用。if/else-if/else標簽類似于Java中的if/else-if/else語句,可根據(jù)一定的條件(Boolean表達式)來選擇執(zhí)行或跳過標簽體的內(nèi)容。
if標簽的屬性如表5-8所示。
【步驟5】運行結(jié)果和調(diào)試。
重新啟動Tomcat服務(wù)器,運行程序,管理員登錄頁面與登錄成功頁面分別如圖5-14和圖5-15所示。圖5-14管理員登錄圖5-15管理員登錄成功一般用戶登錄頁面與登錄成功頁面分別如圖5-16和圖5-17所示。
圖5-16用戶登錄圖5-17用戶登錄成功在圖5-17所示的頁面中沒有出現(xiàn)物品清單,這是怎么回事?究其原因,請讀者仔細觀察,在struts.xml中是通過redirectAction轉(zhuǎn)發(fā)action來進入用戶登錄頁面的,而在user.action的配置中沒有對應(yīng)的action類,只有轉(zhuǎn)發(fā)頁面。前面我們提到,在Struts2中訪問的屬性一定要在Action中存在,并且要有其對應(yīng)的get×××()方法才能訪問到,因此這里訪問不到products變量。那么如何修改呢?最理想的方法就是在login()中把products也放入session范圍,在login()的returnSUCCESS;語句前增加以下代碼:
request.getSession().setAttribute(“products”,getProducts());
把user.jsp代碼中的黑體部分修改如下:
<s:iteratorvalue="#ducts"status="index"id="product_index">
再次運行,用戶登錄成功的界面如圖5-18所示。圖5-18修改用戶登錄成功5.3.2訪問request、session和application對象
在上一小節(jié)中,當用戶登錄成功后,我們將用戶信息保存到Session中,這是ServletAPI中的HttpSession,一般Web開發(fā)中常用ServletAPI中的HttpServletRequest、HttpSession和ServletContext。Struts2框架讓我們可以直接訪問和設(shè)置action及模型對象的數(shù)據(jù),這降低了對HttpServletRequest對象的使用需求。
1.與ServletAPI解耦的訪問方式
為了避免與ServletAPI耦合在一起,方便action類做單頁測試,Struts2框架構(gòu)造了三個Map對象來代替HttpServletRequest、HttpSession和ServletContext。這可以在以下的action中驗證,com.action.sessionway.LoginAction1.java代碼如下:
packagecom.action.sessionway;
importjava.util.Map;
importcom.opensymphony.xwork2.Action;
importcom.opensymphony.xwork2.ActionContext;
publicclassLoginAction1implementsAction{
privateStringuser;
publicStringgetUser(){
returnuser;
}
publicvoidsetUser(Stringuser){
this.user=user;
}
publicStringexecute()throwsException{
ActionContextcontext=ActionContext.getContext();
Maprequest=(Map)context.get(“request”);
Mapsession=context.getSession();
Mapapplication=context.getApplication();
//在請求中放置歡迎信息
request.put("greeting","歡迎來到清風書苑");
//在session中保存對象
session.put(“user”,user);
//統(tǒng)計用戶訪問量,在application中保存用戶訪問量數(shù)據(jù)
Integercount=(Integer)application.get("counter");
if(null==count)
count=newInteger(1);
else
count=newInteger(Value()+1);
application.put("counter",count);
returnSUCCESS;
}
}
2.與ServletAPI耦合的訪問方式
有時候程序中又確實需要直接訪問這些對象,則可以使用org.apache.struts2.ServletActionContext類。com.action.sessionway.LoginAction2.java代碼如下:
packagecom.action.sessionway;
importjavax.servlet.ServletContext;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpSession;
importorg.apache.struts2.ServletActionContext;
importcom.opensymphony.xwork2.Action;
importcom.opensymphony.xwork2.ActionContext;
publicclassLoginAction2implementsAction{
privateStringuser;
publicStringgetUser(){
returnuser;
}
publicvoidsetUser(Stringuser){
this.user=user;
}
publicStringexecute()throwsException{
ActionContextctx=ActionContext.getContext();
HttpServletRequestrequest=(HttpServletRequest)
ctx.get(ServletActionContext.HTTP_REQUEST);
HttpSessionsession=request.getSession();
ServletContextcontext=(ServletContext)
ctx.get(ServletActionContext.SERVLET_CONTEXT);
//在請求中放置歡迎信息
request.setAttribute("greeting","歡迎來到清風書苑");
//在session中保存user對象
session.setAttribute("user",user);
//統(tǒng)計用戶訪問量,在application中保存用戶訪問量數(shù)據(jù)
Integercount=(Integer)context.getAttribute("counter");
if(null==count)
count=newInteger(1);
else
count=newInteger(Value()+1);
context.setAttribute(“counter”,count);
returnSUCCESS;
}
}
3.完善以上action配置
對以上兩個action,需要一個輸出頁面來顯示和配置struts.xml,如果輸出頁面能正常顯示保存在action中的request、session、application對象中的數(shù)據(jù),則說明對象操作成功。
【步驟1】完成訪問頁面session.jsp和輸出頁面sessionok.jsp。
session.jsp中使用超鏈接傳值的方式傳輸user對象,這種方法在程序中經(jīng)常用到,代碼如下:
<body>
使用與ServletAPI解耦的訪問方式
<ahref="
session1.action?user=hellen">request、session和application對象</a>
<br>
使用與ServletAPI耦合的訪問方式
<ahref="
session2.action?user=john">request、session和application對象</a>
</body>
sessionok.jsp中使用EL表達式來獲取三個值,這種方式簡單好用,代碼如下:
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年甘肅文書幼教招聘考試真題
- 2025年度互聯(lián)網(wǎng)安全領(lǐng)域技術(shù)人員保密與競業(yè)限制合同
- 2025年度醫(yī)院陪護人員護理技能提升與雇傭協(xié)議
- 2025年氣動單向隔膜泵項目投資可行性研究分析報告-20241226-193232
- 2025年度新型環(huán)保材料采購合同風險管理與防范
- 物流交易中心項目可行性研究報告申請建議書
- 2025年度物業(yè)管理人員培訓與發(fā)展人工費資助協(xié)議
- 二零二五年度飯店員工勞動保障協(xié)議
- 2025年度抵押機動車跨境交易及借款協(xié)議
- 買購車合同范本
- 新教材青島版六三制四年級下冊科學全冊教案(教學設(shè)計)
- DB11-T 825-2021綠色建筑評價標準
- 醫(yī)院招聘醫(yī)護人員報名登記表
- 完整解讀2022年《義務(wù)教育課程方案》2022年《義務(wù)教育課程方案(2022版)》新課標PPT
- 央企最新版員工手冊vvv
- 新生兒科出科考試試卷試題
- 信息化教學設(shè)計教案大學語文
- 植物的營養(yǎng)器官:根、莖、葉匯總
- 會議、匯報材料排版格式
- 華為公司產(chǎn)品線獎金分配暫行辦法
- 兒童能力評估量表(PEDI拍迪)
評論
0/150
提交評論