《基于JavaEE的電子商務(wù)網(wǎng)站建設(shè)》課件第5章_第1頁
《基于JavaEE的電子商務(wù)網(wǎng)站建設(shè)》課件第5章_第2頁
《基于JavaEE的電子商務(wù)網(wǎng)站建設(shè)》課件第5章_第3頁
《基于JavaEE的電子商務(wù)網(wǎng)站建設(shè)》課件第5章_第4頁
《基于JavaEE的電子商務(wù)網(wǎng)站建設(shè)》課件第5章_第5頁
已閱讀5頁,還剩144頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

第5章Struts2框架基礎(chǔ)5.1Struts2注冊(cè)功能的實(shí)現(xiàn)5.2struts.xml配置詳解5.3增加模型組件與權(quán)限分離的方法

5.1Struts2注冊(cè)功能的實(shí)現(xiàn)

5.1.1Struts2框架在Web應(yīng)用中的環(huán)境搭建

【步驟1】下載Struts2使用的相關(guān)Jar包。

登錄/download.cgi站點(diǎn),查找所需版本,一般下載完整版,即FullDistribution;然后將下載的Zip文件解壓縮。以下為struts-2.0.14-all.zip解壓后包含的文件結(jié)構(gòu):

apps:包含基于Struts2框架的示例應(yīng)用,可以直接部署到服務(wù)器上運(yùn)行;

docs:包含所有Struts2框架的相關(guān)文檔;

lib:包含Struts2框架的核心類庫,以及其所依賴的第三方插件類庫;

src:包含Struts2框架的所有源代碼(開源)。

【步驟2】把Web應(yīng)用需要的Jar包配置到項(xiàng)目中。

配置一個(gè)基本的Struts2應(yīng)用至少包含以下Jar包:

freemaker-2.3.8.jar:Struts2的UI標(biāo)簽?zāi)0迨褂肍reeMaker編寫;

ognl-2.6.11.jar:對(duì)象圖導(dǎo)航語言,Struts2使用的一種表達(dá)式語言;

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文件夾。每個(gè)基于Struts2框架的應(yīng)用都要先提供所需要的Jar包。

按第4章的講解,建立Web工程ch05并將以上的5個(gè)Jar文件復(fù)制到工程的WEB-INF/lib路徑下,則這些包會(huì)自動(dòng)配置到環(huán)境變量中,如圖5-1所示。圖5-1Jar包的導(dǎo)入若看不到【ReferencedLibraries】中的內(nèi)容,可以選中工程并點(diǎn)擊右鍵,在彈出的快捷菜單中選擇【BuildPath】中的【ConfigBuildPath】,將打開如圖5-2所示的界面,則說明導(dǎo)入成功。圖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ù),當(dāng)然也支持最傳統(tǒng)的JSP視圖技術(shù)。

以下Struts2標(biāo)簽實(shí)現(xiàn)登錄表單提交和顯示功能。登錄信息包括兩個(gè)表單域:用戶名(username)和密碼(password)。

1.登錄表單請(qǐng)求頁面

【步驟1】建立login.jsp文件。

使用第4章講解的方法在ch05中新建login.jsp文件,注意文件的放置目錄為ch05/WebRoot。在login.jsp頁面的【Design】視圖中把JSP頁面的pageEncoding屬性修改為“gb2312”(第一行),同時(shí)加入struts標(biāo)簽導(dǎo)入語句(第二行),代碼如下:

<%@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】運(yùn)行注冊(cè)頁面。

用第4章講解的方法在MyEclipse中部署ch05工程,并啟動(dòng)Tomcat,運(yùn)行工程http://localhost/ch05/,顯示如圖5-3所示的界面。讀者在今后的學(xué)習(xí)中也可用此方法來避免文件名的錯(cuò)誤輸入。圖5-3ch05工程運(yùn)行界面點(diǎn)擊login.jsp的超鏈接,顯示表單如圖5-4所示。

圖5-4登錄表單頁面圖

2.注冊(cè)表單響應(yīng)頁面

同請(qǐng)求頁面生成一樣,新建loginok.jsp,僅把【步驟1】的代碼換成如下代碼:

<%@pagelanguage="java"import="java.util.*"

pageEncoding="gb2312"%>

<%@taglibprefix="s"uri="/struts-tags"%>

……

<body>

歡迎<s:propertyvalue="username"/>??!

</body>由于尚未配置Struts2控制器,注冊(cè)響應(yīng)界面無值傳入,因此運(yùn)行界面如圖5-5所示。圖5-5登錄響應(yīng)頁面

3.?Struts2標(biāo)簽簡介

1)標(biāo)簽庫的導(dǎo)入

Struts2標(biāo)簽庫的描述文件包含在Struts2的核心JAR包(struts2-core-2.0.14.jar)中,在META-INF目錄下,文件名為struts-tags.tld。

JSP2.0規(guī)范中規(guī)定,標(biāo)簽庫部署在JAR包中時(shí),標(biāo)簽庫描述符文件必須放在META-INF目錄或其子目錄下,放在META-INF目錄下的TLD文件會(huì)被容器自動(dòng)加載。在struts-tags.tld文件中,設(shè)置了<uri>元素,如下所示:

<uri>/struts-tags</uri>

在JSP頁面中引用Struts2標(biāo)簽庫時(shí),需要使用taglib指令,該指令的uri屬性的值設(shè)為這里的<uri>元素的內(nèi)容。至于prefix屬性,通常設(shè)為“s”,如上面jsp頁面的設(shè)置。

<%@taglibprefix="s"uri="/struts-tags"%>

2)?form標(biāo)簽

Struts2的表單標(biāo)簽可以分為兩類:form標(biāo)簽本身和包裝HTML表單元素的其他標(biāo)簽。下面先介紹form標(biāo)簽。

form標(biāo)簽常用的屬性如表5-1所示。

3)表單元素的其他標(biāo)簽

登錄功能的表單填寫頁面用到兩個(gè)表單標(biāo)簽:textfield和password。這兩個(gè)標(biāo)簽相當(dāng)于HTML表單標(biāo)簽中的text和password標(biāo)簽。這兩個(gè)標(biāo)簽常用的屬性如表5-2所示。

4)數(shù)據(jù)標(biāo)簽property

在上面的loginok.jsp中使用了property標(biāo)簽,很明顯,property標(biāo)簽用于輸出值棧中的對(duì)象屬性值,使用value屬性來指定要輸出的對(duì)象屬性。property標(biāo)簽常用的屬性如表5-3所示。

4.注冊(cè)頁面的純JSP實(shí)現(xiàn)下面提供以上Struts2實(shí)現(xiàn)表單的純JSP編碼,讓讀者用熟悉的語言來對(duì)照Struts2標(biāo)簽的功效。

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>當(dāng)表單提交loginAction.action時(shí),Struts2的FilterDispatcher將自動(dòng)起作用,將用戶請(qǐng)求轉(zhuǎn)發(fā)到對(duì)應(yīng)的Struts2Action,Struts2Action默認(rèn)攔截所有后綴為.action的請(qǐng)求。在Struts2中,struts2-core-2.0.14.jar包中的org.apache.struts2包中有個(gè)perties文件,它定義了Struts2Action默認(rèn)攔截的請(qǐng)求后綴。5.1.3控制器類的實(shí)現(xiàn)

1.代碼實(shí)現(xiàn)

下面就是建立Struts2控制器類的步驟:

【步驟1】建立控制器類com.action.LoginAction.java。

在ch05工程的src目錄下,右鍵單擊【New】的【Class】子菜單,填寫如圖5-6所示的頁面,新建com.action包中的Action文件LoginAction.java,并實(shí)現(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方法處點(diǎn)擊鼠標(biāo)右鍵,選擇【Source】的【GenerateGettersandSetters】,在出現(xiàn)的如圖5-7所示的界面中選中所有屬性。圖5-7get/set方法產(chǎn)生器點(diǎn)擊【OK】按鈕,則會(huì)自動(dòng)產(chǎn)生如下代碼:

publicStringgetUsername(){

returnusername;}

publicvoidsetUsername(Stringusername){

this.username=username;}

publicStringgetPassword(){

returnpassword;}

publicvoidsetPassword(Stringpassword){

this.password=password;

}

2.實(shí)現(xiàn)原理

Struts2的Action接口里定義了五個(gè)常量,一個(gè)execute方法。這五個(gè)常量就是在日常開發(fā)中業(yè)務(wù)邏輯方法返回的字符串,execute方法則是Action接口定義的一個(gè)默認(rèn)的業(yè)務(wù)邏輯方法。五個(gè)常量分別代表特定的含義:●?SUCCESS:表示請(qǐng)求處理成功;

●?ERROR:表示請(qǐng)求處理失?。?/p>

●?NONE:表示請(qǐng)求處理完成后不跳轉(zhuǎn)到任何頁面;

●?INPUT:表示輸入時(shí)如果驗(yàn)證失敗應(yīng)該跳轉(zhuǎn)到什么地方;

●?LOGIN:表示登錄失敗后跳轉(zhuǎn)的目標(biāo)。

這些常量可以簡化和標(biāo)準(zhǔn)化execute方法的返回值,避免直接返回字符串,但是如果有特殊返回意義,則還可以自定義字符串。5.1.4struts.xml配置的實(shí)現(xiàn)

與大部分Java框架類似,Struts2框架也采用XML配置文件來管理Struts2資源。Struts2默認(rèn)配置文件名為struts.xml,該文件要求放在Web應(yīng)用的類加載路徑下,通常放在WEB-INF/classes路徑下。struts.xml配置文件最大的作用就是配置Action和請(qǐng)求之間的對(duì)應(yīng)關(guān)系,并配置邏輯視圖名和物理視圖資源之間的對(duì)應(yīng)關(guān)系。

【步驟1】創(chuàng)建struts.xml文件。

由于MyEclipse的IDE會(huì)自動(dòng)把src目錄下的文件編譯到WEB-INF/classes文件中,所以只要在ch05工程的src文件夾根目錄下建立struts.xml文件即可。右擊src文件夾,選擇【New】菜單下的【XML(BasicTemplates)】,在彈出的圖5-8中把文件名改成struts.xml,直接點(diǎn)擊【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中繼承默認(rèn)的包定義,并給出特定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】項(xiàng)目運(yùn)行

完成配置后可以運(yùn)行本項(xiàng)目。啟動(dòng)服務(wù)器,在IE中輸入地址http://localhost/ch05/login.jsp,將顯示如圖5-9所示的界面。填好信息后,點(diǎn)擊【submit】,將進(jìn)入如圖5-10所示的界面。注意,此時(shí)地址欄的名字為http://localhost/ch05/loginAction.action,但界面內(nèi)容卻是loginok.jsp,說明struts.xml的配置起作用了。

圖5-9運(yùn)行輸入界面圖5-10提交轉(zhuǎn)入頁面對(duì)于整個(gè)登錄的處理流程,可以簡化如下:用戶輸入兩個(gè)參數(shù)username和password,然后向login.action發(fā)送請(qǐng)求,該請(qǐng)求被FilterDispatcher轉(zhuǎn)發(fā)給LoginAction處理。如果LoginAction處理用戶請(qǐng)求后返回success,則返回給用戶loginok.jsp頁面;如果輸入錯(cuò)誤,則系統(tǒng)默認(rèn)返回login.jsp頁面,并要求重新輸入。5.1.5Struts2框架的工作流程

Struts2框架按照模塊,可以分為ServletFilters、Struts核心模塊、攔截器和用戶實(shí)現(xiàn)部分。Struts2官方站點(diǎn)提供的Struts2的整體結(jié)構(gòu)如圖5-11所示。圖5-11Struts2結(jié)構(gòu)圖一個(gè)請(qǐng)求在Struts2框架中的處理大概分為以下幾個(gè)步驟:

(1)客戶端提交一個(gè)(HttpServletRequest)請(qǐng)求。如上文中提交注冊(cè)信息后,在瀏覽器中地址為http://localhost/ch05/loginAction.action,就是提交一個(gè)(HttpServletRequest)請(qǐng)求。

(2)請(qǐng)求被提交到一系列(主要是3層)的過濾器(Filter),如ActionContextCleanUp、其他過濾器(SiteMesh等)、FilterDispatcher。注意:這里是有順序的,先ActionContextCleanUp,然后為其他過濾器(OtherFilters、SiteMesh等),最后到FilterDispatcher。

(3)?FilterDispatcher是控制器的核心,就是MVC的Struts2實(shí)現(xiàn)中控制層(Controller)的核心。

(4)?FilterDispatcher詢問ActionMapper是否需要調(diào)用某個(gè)Action來處理這個(gè)(HttpServletRequest)請(qǐng)求,如果ActionMapper決定需要調(diào)用某個(gè)Action,F(xiàn)ilterDispatcher則把請(qǐng)求的處理交給ActionProxy。

(5)?ActionProxy通過ConfigurationManager(struts.xml)詢問框架的配置文件,找到需要調(diào)用的Action類。例如,注冊(cè)示例將找到LoginAction.java類。

(6)?ActionProxy創(chuàng)建一個(gè)ActionInvocation實(shí)例,同時(shí)ActionInvocation通過代理模式調(diào)用Action。如果在struts.xml文件中配置method參數(shù),則調(diào)用method參數(shù)對(duì)應(yīng)的Action類中的method方法,否則調(diào)用通用的execute()方法來處理用戶請(qǐng)求;但在調(diào)用之前,ActionInvocation會(huì)根據(jù)配置加載Action相關(guān)的所有Interceptor(攔截器)。

(7)一旦Action執(zhí)行完畢,ActionInvocation負(fù)責(zé)根據(jù)struts.xml中的配置找到對(duì)應(yīng)的返回結(jié)果result。

5.2struts.xml配置詳解

5.2.1struts.xml文件的元素結(jié)構(gòu)

struts.xml文件的元素結(jié)構(gòu)圖如圖5-12所示。

在圖5-12中,星號(hào)(*)表示0個(gè)或多個(gè)元素,問號(hào)(?)表示該元素是可選的,加號(hào)(+)表示該元素至少有一個(gè)或多個(gè),沒有添加這三種符號(hào)的元素表明該元素是必需的。圖5-12struts.xml文件的元素結(jié)構(gòu)圖5.2.2包含(include)的配置

在默認(rèn)情況下,Struts2框架將自動(dòng)加載放在WEB-INF/classes路徑下的struts.xml文件中。在大部分應(yīng)用里,隨著應(yīng)用規(guī)模的增加,系統(tǒng)中Action的數(shù)量也將大量增加,導(dǎo)致struts.xml配置文件變得非常臃腫。

為了避免struts.xml文件過于龐大,提高struts.xml文件的可讀性,可以將一個(gè)struts.xml配置文件分解成多個(gè)配置文件,然后在struts.xml文件中包含其他配置文件。<?xmlversion="1.0"encoding="UTF-8"?>

<!--指定Struts2配置文件的DTD信息-->

<!DOCTYPEstrutsPUBLIC

"-//ApacheSoftwareFoundation//DTDStrutsConfiguration2.0//EN"

"/dtds/struts-2.0.dtd">

<!--下面是Struts2配置文件的根元素-->

<struts>

<!--通過include元素導(dǎo)入其他配置文件-->

<includefile="com/action/cart/struts-cart.xml"/>

...

</struts>5.2.3常量(constant)的配置

常量可以在多個(gè)文件中聲明,分別為:

①?struts-default.xml;

②?struts-plugin.xml;

③?struts.xml;

④?perties;

⑤?web.xml。

1.?struts.xml配置常量

struts.xml配置常量使用constant標(biāo)簽,其包含兩個(gè)屬性值:name和value。其中,name是常量的名字,如果定義的常量是Struts2內(nèi)置的屬性,如編碼(struts.i18n.encoding)、國際化資源包文件基名(struts.custom.i18n.resources)等,則可以在perties中查找對(duì)應(yīng)的常量名;value就是常量的值。

<struts>

<constantname="struts.i18n.encoding"value="gb2312"></constant>

<constantname="struts.custom.i18n.resources"

value="message"></constant>

</struts>

2.屬性(properties)文件

perties文件中,每一個(gè)鍵-值對(duì)就是一個(gè)常量

設(shè)置。對(duì)于以上的struts.custom.i18n.resources的常量值為message,這表示在Struts2中定義了一個(gè)名為perties的屬性文件,此文件必須放在WEB-INF/classes的根目錄下。建立屬性文件的步驟為:

【步驟1】新建文件perties。

選擇src文件夾,右擊【New】下的【File】子菜單,在出現(xiàn)的如圖5-13所示的界面中輸入文件名perties,點(diǎn)擊【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中的包,每個(gè)包都包含了將要用到的action、result和攔截器的定義。但是和Java中的包不同的是,Struts2的包可以擴(kuò)展另外的包,從而“繼承”原有包的所有定義,并可添加自己包特有的配置,以及修改原有包的部分配置。struts.xml中的package元素包含的屬性如表5-4所示。在以上屬性中,name的值必須是唯一的,在一個(gè)struts.xml中不能出現(xiàn)兩個(gè)同名的包。extends屬性允許一個(gè)包繼承一個(gè)或多個(gè)先前定義的包的配置,如果定義多個(gè),則用逗號(hào)隔開。在注冊(cè)示例的配置中,表示名為struts2的包繼承struts-default包,這個(gè)包位于struts-default.xml中,是Struts2框架自動(dòng)加載的。?<packagename="struts2"extends="struts-default">

</package>

<packagename="struts-cart"extends="struts2">

</package>

2.?namespace配置

package元素的namespace屬性可以將包中的action配置為不同的名稱空間,這樣在不同名稱空間中可以使用同名action。Struts2框架使用action名字和它所在的名稱空間來標(biāo)識(shí)一個(gè)action。而namespace可以不定義,就是默認(rèn)名稱空間,當(dāng)請(qǐng)求在自己的名稱空間沒有找到對(duì)應(yīng)的action時(shí),就會(huì)自動(dòng)查找默認(rèn)名稱空間中相同名字的請(qǐng)求,如以下編碼:<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>當(dāng)請(qǐng)求/cart/loginAction.action發(fā)生時(shí),Struts2框架首先查找/cart名稱空間的loginAction.action,如果找到了,就執(zhí)行;如果像以上代碼中一樣沒有找到,就會(huì)到默認(rèn)的名稱空間繼續(xù)查找,找到后再執(zhí)行。5.2.5action的配置

Struts的核心是action,通常action類都要實(shí)現(xiàn)com.opensymphony.xwork2.Action接口,實(shí)現(xiàn)該接口的execute()方法。但在實(shí)際開發(fā)中很少直接實(shí)現(xiàn)Action接口,而是繼承ActionSupport類(詳解見第6章)。開發(fā)好action后,就要配置action映射,用來通知Struts2框架,針對(duì)某個(gè)URL的請(qǐng)求應(yīng)該交由哪個(gè)action進(jìn)行處理。

1.?action映射

action映射就是將一個(gè)請(qǐng)求URI(即action名字)映射到一個(gè)action類,當(dāng)一個(gè)請(qǐng)求匹配某個(gè)action名字時(shí),框架就使用這個(gè)映射來確定如何處理請(qǐng)求。struts.xml文件中的每一個(gè)action元素就是一個(gè)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àng):

■一般不允許出現(xiàn)斜杠(/);

■名字中盡量不要使用點(diǎn)號(hào)(.)和連字符(-)。

2.使用method屬性

在業(yè)務(wù)邏輯開發(fā)中,為了節(jié)省action的數(shù)量,通常在一個(gè)action類中編寫多個(gè)業(yè)務(wù)方法,如數(shù)據(jù)庫的CRUD操作(Create、Read、Update、Delete)。大家到目前也應(yīng)該清楚,在執(zhí)行action時(shí),默認(rèn)調(diào)用的方法是execute(),那么如何讓不同請(qǐng)求到來時(shí),使用框架去調(diào)用同一個(gè)action的不同方

法呢?我們先看以下action代碼片段(來源于5.3節(jié)的示例):

publicclassLoginActionimplementsAction{

publicStringexecute()throwsException{

returnSUCCESS;}

publicStringlogin()throwsException{

returnSUCCESS;}

}

LoginAction.java中定義了兩個(gè)邏輯方法execute()和login()。注意,login()的結(jié)構(gòu)必須符合execute()的結(jié)構(gòu)publicStringexecute()throwsException{}。那么在配置action時(shí),可以通過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ù)量會(huì)非常龐大,這時(shí)可使用通配符映射來減少action配置的數(shù)量。

代碼如下:

<actionname="*Crud"class="example.Crud"

method="{1}">

這里,當(dāng)在應(yīng)用中將action指定為“editCrud”時(shí),將調(diào)用editCrudAction處理類實(shí)例中的edit方法。另外一種方法是通過action的后綴來匹配方法名,并且通過感嘆號(hào)、下劃線或者其它特殊字符將其分開,如action="/Crud_input.action"或action="/Crud_delete.action"。下面的代碼片斷演示了在action名稱的最后使用星號(hào)通配符的示例:

<actionname="Crud_*"class="example.Crud"method=

"{1}">

當(dāng)然通配符除了*號(hào)外,還有其他內(nèi)容:

*:匹配0個(gè)或多個(gè)字符,斜杠(/)字符除外;

**:匹配0個(gè)或多個(gè)字符,包括斜杠(/)字符;

\:反斜杠字符被用作轉(zhuǎn)義序列,例如,\*匹配星號(hào)(*),\\匹配反斜杠字符(\)。5.2.6Result的配置

1.結(jié)構(gòu)映射

在struts.xml文件中,使用result元素來配置result映射。result元素的屬性如表5-6所示。

2.常用結(jié)果類型

1)?dispatcher結(jié)果類型

Struts2將dispatcher設(shè)為默認(rèn)的結(jié)果類型,就像在登錄示例中沒有定義結(jié)果類型,但都默認(rèn)使用dispatcher轉(zhuǎn)發(fā)。

dispatcher轉(zhuǎn)發(fā)地址中可以使用OGNL表達(dá)式(參見第6章),例如在購物車系統(tǒng)中,每個(gè)商品都有一個(gè)id號(hào)來標(biāo)識(shí),當(dāng)用戶點(diǎn)擊購買時(shí),此請(qǐng)求一定帶有id號(hào),傳送此id的地址可以寫成:

<result>/cart.jsp?id=${id}</result>

2)?redirect結(jié)果類型

redirect結(jié)果類型相當(dāng)于使用HttpServletResponse的sendRedirect方法將請(qǐng)求重定向到指定的URL,就是重定向后的URL地址是實(shí)際訪問的頁面地址,而不是action的名字。由于這個(gè)原因,使用redirect結(jié)果類型可以避免重復(fù)提交表單的操作。

3)?redirectAction結(jié)果類型

redirectAction結(jié)果類型和redirect結(jié)果類型的后臺(tái)工作原理是一樣的,都是使用HttpServletResponse的sendRedirect方法將請(qǐng)求重定向到指定的URL。但是redirectAction結(jié)果類型主要用于重定向到action。具體示例請(qǐng)參照下面第3點(diǎn)“動(dòng)態(tài)結(jié)果”的內(nèi)容。

3.動(dòng)態(tài)結(jié)果

所謂動(dòng)態(tài)結(jié)果,是指在配置時(shí)你不知道要執(zhí)行哪個(gè)結(jié)果,在運(yùn)行時(shí)才能確定執(zhí)行的結(jié)果。也就是說,利用表達(dá)式來配置結(jié)果,在運(yùn)行時(shí),框架解析并計(jì)算表達(dá)式,根據(jù)表達(dá)式的值來確定要執(zhí)行的結(jié)果。

例如在登錄功能中,如果一個(gè)系統(tǒng)有多個(gè)不同的角色管理,那么登錄成功后應(yīng)該進(jìn)入不同的操作界面,以達(dá)到操作權(quán)限的分離。分析下面的代碼片段(來源于5.3節(jié)的示例):

publicclassLoginActionimplementsAction{

……

//用于保存請(qǐng)求重定向到的action名字;

privateStringnextAction;

……

publicStringgetNextAction(){

returnnextAction;}

publicStringlogin()throwsException{

……

if(…){//驗(yàn)證用戶是否為管理員;

nextAction=“manager”;

}else{

nextAction=“user”;}

returnSUCCESS;

……

}

}

LoginAction在用戶登錄驗(yàn)證成功后,判斷用戶的權(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屬性的值,而這個(gè)值要到運(yùn)行時(shí)刻才能確定。

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{

//以一個(gè)常量數(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(),在此方法中把登錄名放進(jìn)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[];

//用于保存請(qǐng)求重定向到的action名字;

privateStringnextAction;

……//省略u(píng)sername與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配置。

為了運(yùn)行action文件中的login()方法,需要對(duì)struts.xml文件進(jìn)行修改,使得登錄成功后管理員轉(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進(jìn)行轉(zhuǎn)發(fā),因此默認(rèn)使用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標(biāo)簽完成循環(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">

<!--判斷序號(hào)是否為偶數(shù)-->

<s:iftest="#index.odd==false">

<s:propertyvalue="product_index"/>

</s:if>

<s:else><br></s:else>

</s:iterator>

</body>■?iterator標(biāo)簽

iterator標(biāo)簽用于迭代一個(gè)集合(包括Collection、Map、Enumeration、Iterator或者array數(shù)組)。iterator標(biāo)簽在迭代過程中,會(huì)把迭代的每一個(gè)對(duì)象暫時(shí)壓入值棧,這樣在標(biāo)簽內(nèi)部就可以直接訪問對(duì)象的屬性和方法,在標(biāo)簽執(zhí)行完畢后,位于棧頂?shù)膶?duì)象就會(huì)被刪除;在第二次迭代過程中,再壓入新的對(duì)象。

iterator標(biāo)簽的屬性如表5-7所示。■?if/else-if/else標(biāo)簽

if標(biāo)簽用于基本的流程控制,它可以單獨(dú)使用,也可

以和一個(gè)或多個(gè)else-if標(biāo)簽,或者和一個(gè)else標(biāo)簽一起使

用。if/else-if/else標(biāo)簽類似于Java中的if/else-if/else語句,可根據(jù)一定的條件(Boolean表達(dá)式)來選擇執(zhí)行或跳過標(biāo)簽體的內(nèi)容。

if標(biāo)簽的屬性如表5-8所示。

【步驟5】運(yùn)行結(jié)果和調(diào)試。

重新啟動(dòng)Tomcat服務(wù)器,運(yùn)行程序,管理員登錄頁面與登錄成功頁面分別如圖5-14和圖5-15所示。圖5-14管理員登錄圖5-15管理員登錄成功一般用戶登錄頁面與登錄成功頁面分別如圖5-16和圖5-17所示。

圖5-16用戶登錄圖5-17用戶登錄成功在圖5-17所示的頁面中沒有出現(xiàn)物品清單,這是怎么回事?究其原因,請(qǐng)讀者仔細(xì)觀察,在struts.xml中是通過redirectAction轉(zhuǎn)發(fā)action來進(jìn)入用戶登錄頁面的,而在user.action的配置中沒有對(duì)應(yīng)的action類,只有轉(zhuǎn)發(fā)頁面。前面我們提到,在Struts2中訪問的屬性一定要在Action中存在,并且要有其對(duì)應(yīng)的get×××()方法才能訪問到,因此這里訪問不到products變量。那么如何修改呢?最理想的方法就是在login()中把products也放入session范圍,在login()的returnSUCCESS;語句前增加以下代碼:

request.getSession().setAttribute(“products”,getProducts());

把user.jsp代碼中的黑體部分修改如下:

<s:iteratorvalue="#ducts"status="index"id="product_index">

再次運(yùn)行,用戶登錄成功的界面如圖5-18所示。圖5-18修改用戶登錄成功5.3.2訪問request、session和application對(duì)象

在上一小節(jié)中,當(dāng)用戶登錄成功后,我們將用戶信息保存到Session中,這是ServletAPI中的HttpSession,一般Web開發(fā)中常用ServletAPI中的HttpServletRequest、HttpSession和ServletContext。Struts2框架讓我們可以直接訪問和設(shè)置action及模型對(duì)象的數(shù)據(jù),這降低了對(duì)HttpServletRequest對(duì)象的使用需求。

1.與ServletAPI解耦的訪問方式

為了避免與ServletAPI耦合在一起,方便action類做單頁測試,Struts2框架構(gòu)造了三個(gè)Map對(duì)象來代替HttpServletRequest、HttpSession和ServletContext。這可以在以下的action中驗(yàn)證,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();

//在請(qǐng)求中放置歡迎信息

request.put("greeting","歡迎來到清風(fēng)書苑");

//在session中保存對(duì)象

session.put(“user”,user);

//統(tǒng)計(jì)用戶訪問量,在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耦合的訪問方式

有時(shí)候程序中又確實(shí)需要直接訪問這些對(duì)象,則可以使用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);

//在請(qǐng)求中放置歡迎信息

request.setAttribute("greeting","歡迎來到清風(fēng)書苑");

//在session中保存user對(duì)象

session.setAttribute("user",user);

//統(tǒng)計(jì)用戶訪問量,在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配置

對(duì)以上兩個(gè)action,需要一個(gè)輸出頁面來顯示和配置struts.xml,如果輸出頁面能正常顯示保存在action中的request、session、application對(duì)象中的數(shù)據(jù),則說明對(duì)象操作成功。

【步驟1】完成訪問頁面session.jsp和輸出頁面sessionok.jsp。

session.jsp中使用超鏈接傳值的方式傳輸user對(duì)象,這種方法在程序中經(jīng)常用到,代碼如下:

<body>

使用與ServletAPI解耦的訪問方式

<ahref="

session1.action?user=hellen">request、session和application對(duì)象</a>

<br>

使用與ServletAPI耦合的訪問方式

<ahref="

session2.action?user=john">request、session和application對(duì)象</a>

</body>

sessionok.jsp中使用EL表達(dá)式來獲取三個(gè)值,這種方式簡單好用,代碼如下:

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論