基于新信息技術(shù)的Java-EE應(yīng)用開發(fā)實訓(xùn)教程課件:Struts 2核心_第1頁
基于新信息技術(shù)的Java-EE應(yīng)用開發(fā)實訓(xùn)教程課件:Struts 2核心_第2頁
基于新信息技術(shù)的Java-EE應(yīng)用開發(fā)實訓(xùn)教程課件:Struts 2核心_第3頁
基于新信息技術(shù)的Java-EE應(yīng)用開發(fā)實訓(xùn)教程課件:Struts 2核心_第4頁
基于新信息技術(shù)的Java-EE應(yīng)用開發(fā)實訓(xùn)教程課件:Struts 2核心_第5頁
已閱讀5頁,還剩108頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

6.1Struts2配置聲明6.2實現(xiàn)Action6.3配置處理結(jié)果6.4攔截器6.1Struts2配置聲明6.1.1配置聲明方式聲明應(yīng)用程序有兩種方式:基于XML或properties配置文件的方式和通過Java注解方式。如圖6-1所示,無論是使用配置文件方式還是使用Java注解方式聲明應(yīng)用程序的Struts2組件,框架都會將它們轉(zhuǎn)化為相同的運行時組件。若使用XML配置文件的方式,則用帶有描述應(yīng)用程序的動作、結(jié)果以及攔截器等元素來配置XML文件。若使用Java注解方式,沒有XML文件,則所有的元素數(shù)據(jù)都集中在Java注解中,這些注解直接駐留在實現(xiàn)動作的類對應(yīng)的Java源文件代碼中。6.1.2配置文件概述Struts2提供了多種可選的配置文件形式,根據(jù)這些配置文件的名稱、所在位置、作用范圍和用途制作了一張配置文件的概覽表,如表6-1所示。6.1.3struts.xml配置文件Struts2的核心是Action,而Action的核心則是struts.xml。struts.xml集中了所有頁面的導(dǎo)航定義。對于大型Web項目來說,通過struts.xml配置文件即可迅速把握項目脈絡(luò),這對于前期的開發(fā),以及后期的維護、升級都是大有裨益的。掌握struts.xml是掌握Struts2項目的關(guān)鍵所在。本節(jié)通過代碼示例來講解配置文件的相關(guān)知識。struts.xml文件的定義:<?xmlversion="1.0"encoding="gb2312"?><!DOCTYPEstrutsPUBLIC"-//ApacheSoftwareFoundation//DTDStrutsConfiguration2.3//EN""/dtds/struts-2.3.dtd"><struts><!--Action所在包定義--><packagename="ch02"extends="struts-default"><!--全局導(dǎo)航頁面定義--><global-results><resultname="global">/jsp/login.jsp</result></global-results><!--Action名字,類以及導(dǎo)航頁面定義--><!--通過Action類處理剛才導(dǎo)航的Action定義--><actionname="Login"class="com.example.struts.action.LoginAction"><resultname="input">/jsp/login.jsp</result><resultname="success">/jsp/success.jsp</result></action><!--直接導(dǎo)航的Action定義--><actionname="index">

<result>/jsp/login.jsp</result> </action></package></struts>代碼解釋如下:(1)struts.xml第一行是所有xml文件都具有的聲明,常以“<?”開始,以“?>”結(jié)束。Version是必須指定的,該屬性一般都為1.0,表明該文檔遵守xml1.0規(guī)范。Encoding是可選的,如果不寫則默認為UTF-8,該文件代碼中的gb2312表明該文件的編碼集是gb2312,且支持中文字符。常見的字符編碼集有支持簡體中文的gb2312,支持繁體中文的GBK,支持西歐字符的ISO8859-1以及通用的國際編碼UTF-8。DTD文件必須被聲明,它表明struts.xml是支持Struts2.0的文檔類型定義。DTD全稱為DocumentTypeDefination(文檔類型定義)。(2)struts.xml文件中所有的屬性定義都是以“<struts>”開始,以“</struts>”結(jié)束的。6.1.4包和命名空間Struts2使用包來組織Action,因此,將Action定義放在包定義下,并定義Action通過使用package下的action子元素來完成,而每個package元素配置一個包。Struts2框架中核心組件是Action、攔截器等。Struts2框架使用包來管理Action和攔截器等,每個包就是多個Action、多個攔截器、多個攔截器引用的集合。配置package元素時必須指定name屬性,這個屬性是引用包的唯一標(biāo)識。除此之外,還可以指定一個可選的extends屬性。注意,extends屬性值必須是另一個包的name屬性。指定extends屬性表示讓一個包繼承另一個包,子包可以從一個或多個父包中繼承攔截器、攔截器棧、action等配置。Struts2還提供了一種抽象包。所謂抽象包,就是不包含Action定義的包。為了顯示指定一個抽象包,可以在package元素中增加abstract="true"屬性。在struts.xml文件中,package元素用于定義包配置,每個package元素定義了一個包配置。定義package元素時可以指定如下幾個屬性:name:必需屬性,該屬性指定了包的名字,此名字是該包被其他包引用的key。extends:可選屬性,該屬性指定包繼承其他包。可以繼承其他包中的Action定義、攔截器定義等。namespace:可選屬性,該屬性定義包的命名空間。如果沒有指定namespace屬性,即使用默認的命名空間,則默認的命名空間總是""。如果指定了命名空間,則該包下所有Action處理的URL均應(yīng)是命名空間+Action名。abstract:可選屬性,它指定包是否是一個抽象包。抽象包中不能包含Action定義。下面是一個簡單的struts.xml配置文件范例。在下面的struts.xml文件中配置了兩個包,其中名為default的包繼承了Struts2框架的默認包:struts-default。<struts><!--配置第一個包,該包名為default,繼承struts-default--><packagename="default"extends="struts-default"><!--下面定義了攔截器部分--><interceptors><!--定義攔截器棧--><interceptor-stackname="crudStack">

<interceptor-refname="params"/><interceptor-refname="defaultStack"/></interceptors-stack></interceptors><default-action-refname="showcase"/><!--定義一個Action,該Action直接映射到showcase.jsp頁面--><actionname="showcase"><result>showcase.jsp</result></action><!--定義一個Action,該Action類為lee.DateAction--><actionname="Date"class="lee.DateAction"><resultname="success">/date.jsp</result></action></package><!--定義名為skill包,該Action繼承default的包--><packagename="skill"extends="default"namespace="/skill"><!--定義默認的攔截器引用--><default-interceptor-refname="crudStack"/><!--定義名為Edit的Action,該Action對應(yīng)的處理類為lee.SkillAction--><actionname="Edit"class="lee.SkillAction"><result>/empmanager/editSkill.jsp</result><interceptor-refname="params"/><interceptor-refname="basicStack"/></action><!--定義名為save的Action,該Action對應(yīng)的處理類為lee.SkillAction,使用save方法作為處理方法--><actionname="save"class="lee.SkillAction"method="save"><resultname="input">/empmanager/editSkill.jsp</result><resultname="redirect">/edit.action?skillName=${currentS}</result></action><!--定義名為Delete的Action,該Action對應(yīng)的處理類為lee.SkillAction,使用delete方法作為處理方法--><actionname="Delete"class="lee.SkillAction"method="delete"><resultname="error">/empmanager/editSkill.jsp</result><resultname="redirect">/edit.action?skillName=${currentS}</result></action></package></struts>從前面內(nèi)容可以看出,每定義一個package元素,都可以指定一個namespace屬性,用于指定該包對應(yīng)的命名空間。Struts2之所以提供命名空間的功能,主要是為了處理同一個Web應(yīng)用中包含同名Action的情形。Struts2以命名空間的方式來管理Action,同一個命名空間里不能有同名的Action,不同的命名空間里可以有同名的Action。Struts2不支持為單獨Action設(shè)置命名空間,它通過為包指定namespace屬性來為包下所有的Action指定共同的命名空間。如果配置package時沒有指定namespace屬性,則包中所有Action均處于默認包空間下。6.1.5配置Action工程越大,struts.xml配置文件就越大,并且越來越復(fù)雜,這樣不便于閱讀。此時可以將struts.xml文件進行拆解。以下是改進的struts.xml配置文件。<?xmlversion="1.0"encoding="UTF-8"?><!DOCTYPEstrutsPUBLIC"-//ApacheSoftwareFoundation//DTDStrutsConfiguration2.3//EN""/dtds/struts-2.3.dtd"><struts><constantname="struts.action.extension"value="action"/>

<!--Action所在包定義-->

<packagename="default"namespace="/"extends="struts-default"><!--默認Action定義--><default-action-refname="index"/>

<!--全局導(dǎo)航頁面定義--><global-results><resultname="error">/error.jsp</result></global-results>

<!--全局異常頁面定義--><global-exception-mappings><exception-mappingexception="java.lang.Exception"result="error"/></global-exception-mappings>

<!--Action重定向--><actionname="index"><resulttype="redirectAction"><paramname="actionName">HelloWorld</param><paramname="namespace">/example</param></result></action></package><includefile="struts-login.xml"/></struts>分步講解:首先使用<constant>標(biāo)簽設(shè)置action的后綴,即<constantname="struts.action.extension"value="action"/>接著定義了包的位置以及默認的Action(訪問默認會直接定位到指定的“index”Action):<!--Action所在包定義--><packagename="default"namespace="/"extends="struts-default"><!--默認Action定義--><default-action-refname="index"/>配置全局異常處理頁面,當(dāng)發(fā)生異常時跳轉(zhuǎn)到/error.jsp頁面:<!--全局導(dǎo)航頁面定義--><global-results><resultname="error">/error.jsp</result></global-results>

<!--全局異常頁面定義--><global-exception-mappings><exception-mappingexception="java.lang.Exception"result="error"/></global-exception-mappings>對默認的Action進行定義。默認的“index”Action只是一個重定向操作。重定向跳轉(zhuǎn)到命名空間是“/example”下面名為“HelloWorld”的Action。<!--Action重定向--><actionname="index"><resulttype="redirectAction"><paramname="actionName">HelloWorld</param><paramname="namespace">/example</param></result></action></package>可以使用<include>標(biāo)簽,模塊化管理struts.xml配置文件。<include>標(biāo)簽用來導(dǎo)入一個子文件,子文件與struts.xml有著同樣的結(jié)構(gòu),使用相同的配置語法。以下是include進來的struts-login.xml的代碼。<?xmlversion="1.0"encoding="UTF-8"?><!DOCTYPEstrutsPUBLIC"-//ApacheSoftwareFoundation//DTDStrutsConfiguration2.3//EN""/dtds/struts-2.3.dtd"><struts><packagename="example"namespace="/example"extends="default"><!—Action典型配置,指定nameclass屬性,包含result節(jié)點配置--><actionname="HelloWorld"class="example.HelloWorld">

<result>/example/HelloWorld.jsp</result></action>

</package></struts>子文件struts-login.xml和struts.xml的結(jié)構(gòu)是一樣的,在該文件中定義了命名空間“/example”,在命名空間里面定義了“HelloWorld”的Action。6.2實現(xiàn)Action6.2.1POJO實現(xiàn)ActionStruts2不要求Action類繼承任何Struts2基類,或者實現(xiàn)任何Struts2接口。在這種設(shè)計方式下,Struts2的Action類是一個普通的POJO(通常應(yīng)該包含一個無參數(shù)的execute方法),其代碼有很好的復(fù)用性。Struts2通常直接使用Action來封裝HTTP請求參數(shù),因此,Action類里還應(yīng)該包含與請求參數(shù)對應(yīng)的屬性,并且為這些屬性提供對應(yīng)的setter和getter方法。例如,用戶請求包含user和pass兩個請求參數(shù),那么Action類應(yīng)該提供user和pass兩個屬性來封裝用戶的請求參數(shù),并且為user和pass提供對應(yīng)的setter和getter方法。下面是處理該請求的Action類的代碼片段://處理用戶請求的Action類,只是一個POJO,無須繼承任何基類,無須實現(xiàn)任何接口publicclassLoginAction{//提供兩個屬性來封裝HTTP請求參數(shù)privateStringuser;privateStringpass;//user屬性的getter和setter方法publicvoidsetUser(Stringuser){ this.user=user;}publicStringgetUser(){return(this.user);}//pass屬性的getter和setter方法publicvoidsetpass(Stringpass){this.pass=pass;}

publicStringgetPass(){return(this.pass);}//Action類默認處理用戶請求的方法:execute方法publicStringexecute(){//返回處理結(jié)果字符串return"login";}}上面的Action類只是一個普通的Java類,這個Java類提供了兩個屬性:user和pass(如程序中粗體字代碼所示),并為這兩個屬性提供了setter和getter方法,這兩個屬性分別對應(yīng)兩個HTTP請求參數(shù)。LoginAction中的execute()方法就是處理用戶請求的邏輯控制方法??梢栽趕truts.xml配置文件中配置Action相關(guān)的映射。<actionname="LoginAction"class="example.LoginAction"><result>/example/Welcome.jsp</result><resultname="login">/example/Login.jsp</result></action>上面配置Action的代碼是基本配置,定義Action時,至少需要指定該Action的name屬性,此name屬性既是Action的名字,又指定了Action對應(yīng)的請求URL的前半部分。除此之外,還需要為action元素指定一個class屬性,其中class屬性指定了該Action的實現(xiàn)類。Action只是一個邏輯控制器,它并不直接對瀏覽者生成任何響應(yīng)。因此,Action處理完用戶請求后,需要將指定的視圖資源呈現(xiàn)給用戶。因此,配置Action時,應(yīng)該配置邏輯視圖和物理視圖資源之間的映射。配置邏輯視圖和物理視圖之間的映射關(guān)系是通過<result>元素來定義的,每個<result>元素定義邏輯視圖和物理視圖之間的一次映射。在Action類的execute()方法中返回的字符串“l(fā)ogin”,此時會根據(jù)<result>標(biāo)簽中定義的name屬性找到對應(yīng)的物理視圖。上面示例會映射跳轉(zhuǎn)第二個<result>標(biāo)簽指向的/example/Login.jsp頁面。第一個<result>標(biāo)簽中沒有設(shè)置name屬性,其默認值為“success”。Action類里的屬性,不僅可用于封裝請求參數(shù),還可用于封裝處理結(jié)果。例如,在前面的Action代碼中看到,如果希望將服務(wù)器提示的“登錄成功”在下一個頁面中輸出,那么可以在Action類中增加一個tip屬性,并為該屬性提供對應(yīng)的setter和getter方法,即為Action類增加如下代碼片段://封裝處理結(jié)果的tip屬性privateStringtip;//tip屬性對應(yīng)的setter和getter方法publicStringgetTip(){returntip;}publicvoidsetTip(Stringtip){this.tip=tip;}一旦在Action中設(shè)置了tip屬性的值,就可以在下一個頁面中使用Struts2標(biāo)簽來輸出該屬性的值。在JSP頁面中輸出tip屬性值的代碼片段如下:<!--使用Struts2標(biāo)簽來輸出tip屬性值--><s:propertyvalue="tip"/>系統(tǒng)不會嚴(yán)格區(qū)分Action里哪個屬性是用于封裝請求參數(shù)的,哪個屬性是封裝處理結(jié)果的。對系統(tǒng)而言,封裝請求參數(shù)的屬性和封閉處理結(jié)果的屬性是完全平等的。如果用戶的HTTP請求里包含了名為tip的請求參數(shù),則系統(tǒng)會調(diào)用Action類的voidseTip(Srtingtip)方法,那么名為tip的請求參數(shù)將無法傳入Action。同樣,在JSP頁面中輸出Action屬性時,系統(tǒng)也不會區(qū)分該屬性是用于封裝請求參數(shù)的,還是用于封裝處理結(jié)果的。因此,使用Struts2的標(biāo)簽既可以輸出Action的處理結(jié)果,也可以輸出HTTP請求參數(shù)值。從上面代碼中看到,需要在JSP頁面輸出的處理結(jié)果是一個簡單的字符串,可以使用<s:propert>標(biāo)簽來控制輸出。實際上,Action類里可以封裝非常復(fù)雜的屬性,包括其他用戶自定義的類、數(shù)組、集合對象和Map對象等。對于這些復(fù)雜類型的輸出,一樣可通過Struts2的標(biāo)簽來完成。6.2.2繼承ActionSupport為了讓用戶開發(fā)的Action類更規(guī)范,Struts2提供了一個Action接口,這個接口定義了Struts2的Action處理類應(yīng)該實現(xiàn)的規(guī)范。下面是標(biāo)準(zhǔn)Action接口的代碼:publicinterfaceAction{/***Theactionexecutionwassuccessful.Showresult*viewtotheenduser.*/publicstaticfinalStringSUCCESS="success";/***Theactionexecutionwassuccessfulbutdonot*showaview.Thisisusefulforactionsthatare*handlingtheviewinanotherfashionlikeredirect.*/publicstaticfinalStringNONE="none";/***Theactionexecutionwasafailure.*Showanerrorview,possiblyaskingthe*usertoretryenteringdata.*/publicstaticfinalStringERROR="error";/***Theactionexecutionrequiremoreinput*inordertosucceed.*Thisresultistypicallyusedifaform*handlingactionhasbeenexecutedsoas*toprovidedefaultsforaform.The*formassociatedwiththehandlershouldbe*showntotheenduser.*<p/>*Thisresultisalsousedifthegiveninput*paramsareinvalid,meaningtheuser*shouldtryprovidinginputagain.*/publicstaticfinalStringINPUT="input";/***Theactioncouldnotexecute,sincethe*usermostwasnotloggedin.Theloginview*shouldbeshown.*/publicstaticfinalStringLOGIN="login";/***Wherethelogicoftheactionisexecuted.**@returnastringrepresentingthelogicalresultoftheexecution.

*Seeconstantsinthisinterfaceforalistofstandardresultvalues.*@throwsExceptionthrownifasystemlevelexceptionoccurs.*<b>Note:</b>Applicationlevelexceptionsshouldbehandledbyreturning*anerrorvalue,suchas<code>Action.ERROR</code>.*/publicStringexecute()throwsException;}上面的Action接口里只定義了一個execute方法,該接口的規(guī)范規(guī)定了Action類應(yīng)該包含一個execute方法,并返回一個字符串。除此之外,該接口還定義了5個字符串常量,它們的作用是統(tǒng)一execute方法的返回值。6.2.3動態(tài)方法調(diào)用Struts2同樣提供了這種包含處理多個處理邏輯的Action,從而允許一個Action內(nèi)包含多個控制處理邏輯。例如對于同一個表單,當(dāng)用戶通過不同的提交按鈕來提交同一個表單時,系統(tǒng)需要使用Action的不同方法來處理用戶請求,這就需要讓同一個Action里包含多個控制處理邏輯??慈鐖D6-2所示的JSP頁面。上面的JSP頁面包含兩個提交按鈕,分別提交給Action的不同方法進行處理。其中,“登錄”按鈕希望使用登錄邏輯來處理請求,而“注冊”按鈕則希望使用注冊邏輯來處理請求。此時,可以采用DMI(DynamicMethodsInvocation,動態(tài)方法調(diào)用)來處理這種請求。動態(tài)方法調(diào)用是指表單元素的Action并不是直接等于某個Action的名字,而是以如下形式來指定Form的Action屬性:<!--action屬性為actionName!methodName的形式其中ActionName指定提交到哪個Action,而methodName指定提交到指定方法-->Action="ActionName!methodName"上面JSP頁面“注冊”按鈕的代碼如下:<!--“注冊”按鈕是一個沒有任何動作的按鈕,但單擊該按鈕時觸發(fā)regist函數(shù)--> <inputtype="submit"value="注冊"onClick="regist();"/>regist函數(shù)的代碼如下:functionregist(){//獲取JSP頁面中的一個表單元素targetForm=document.forms[0];//動態(tài)修改目標(biāo)表單的action屬性targetForm.action="login!regist";}修改后的Action屬性為:login!regist。實質(zhì)就是將表單提交給LoginRegistAction的regist方法處理。LoginRegistAction類的代碼如下:publicclassLoginRegistActionextendsActionSupport{//封裝用戶請求參數(shù)的兩個屬性privateStringusername;privateStringpassword;//封裝處理結(jié)果的tip屬性privateStringtip;//username屬性對應(yīng)的setter和getter方法publicStringgetUsername()

{returnusername;}publicvoidsetUsername(Stringusername){this.username=username;}//password屬性對應(yīng)的getter和setter方法publicStringgetPassword(){returnpassword;}publicvoidsetPassword(Stringpassword){this.password=password;}//tip屬性對應(yīng)的setter和getter方法publicStringgetTip(){returntip;}publicvoidsetTip(Stringtip){this.tip=tip;}//Action包含的注冊控制邏輯

publicStringregist()throwsException{ActionContext.getContext().getSession().put("user",getUsername());setTip("恭喜您,"+getUsername()+",您已經(jīng)注冊成功!");returnSUCCESS;}//Action默認包含的控制邏輯publicStringexecute()throwsException{if(getUsername().equals("bruce")&&getPassword().equals("bruce")){ActionContext.getContext().getSession().put("user",getUsername());setTip("歡迎,"+getUsername()+",您已經(jīng)登錄成功!");returnSUCCESS;}else{returnERROR;}}}當(dāng)瀏覽者單擊“注冊”按鈕時,表單的Action被修改為login!regist,系統(tǒng)將提交給LoginAction(即LoginRegistAction)的regist方法處理。因此,如果單擊“注冊”按鈕將看到如圖6-3所示的頁面。6.2.4指定method屬性及使用通配符Struts2還提供了一種將一個Action處理類定義成多個邏輯Action的處理方法。如果在配置<action>元素時,指定action的method屬性,則可以讓Action類調(diào)用指定方法,而不是execute方法來處理用戶請求。例如,有如下配置片段:<!--定義名為Login的Action,該Action的實現(xiàn)類為LoginAction,處理用戶請求的方法為login--><actionname="Login"class="example.LoginAction"method="login"/>…</action>通過這種方式可以將一個Action類定義成多個邏輯Action,即Action類的每個處理方法都映射成一個邏輯Action,前提是這些方法具有相似的方法簽名:方法形參列表為空,方法返回值為String。下面是本示例的struts.xml文件代碼。<?xmlversion="1.0"encoding="GBK"?><!DOCTYPEstrutsPUBLIC"-//ApacheSoftwareFoundation//DTDStrutsConfiguration2.3//EN""/dtds/struts-2.3.dtd"><struts><!--配置了一個package元素--><packagename="default"extends="struts-default"><!--配置loginAction,處理類為LoginRegistAction默認使用execute方法處理請求--><actionname="login"class="example.LoginRegistAction"><!--定義邏輯視圖和物理視圖之間的映射關(guān)系--><resultname="input">/longin.jsp</result><resultname="error">/error.jsp</result><resultname="success">/welcome.jsp</result> </action><!--配置registAction,處理類為LoginRegistAction指定使用regist方法處理請求--><actionname="regist"class="example.LoginRegistAction"method="regist"><!--定義邏輯視圖和物理視圖之間的映射關(guān)系-->

<resultname="input">/longin.jsp</result><resultname="error">/error.jsp</result><resultname="success">/welcome.jsp</result></action></package></struts>上面定義了login和regist兩個邏輯Action,它們對應(yīng)的處理類都是example.LoginRegistAction。login和regist兩個Action雖然有相同的處理類,但處理邏輯不同——處理邏輯通過method方法指定,其中名為login的Action對應(yīng)的處理邏輯為默認的execute方法,而名為regist的Action對應(yīng)的處理邏輯為指定的regist方法。將一個Action處理類定義成兩個邏輯Action后,可以再修改JSP頁面的JavaScript代碼。修改regist函數(shù)的代碼如下:functionregist(){//獲取頁面的第一個表單targetForn=document.forms[0];//動態(tài)修改表單的action屬性targetform.action="regist.action";}通過這種方式,也可以實現(xiàn)上面的效果——當(dāng)瀏覽者單擊“登錄”按鈕時,將提交給Action類的登錄邏輯處理;當(dāng)瀏覽者單擊“注冊”按鈕時,將提交給Action類的注冊邏輯處理。再次查看上面struts.xml文件中兩個<action>元素定義,發(fā)現(xiàn)兩個Action定義的絕大部分均相同,因此,這種定義相當(dāng)冗余。為了解決這個問題,Struts2還有另一種形式的動態(tài)方法調(diào)用:使用通配符方式。在配置<action>元素時,需要指定name、class和method屬性,其中name屬性可使用模式字符串(允許用“*”代表一個或多個任意字符),表明該Action可以處理所有能匹配該模式字符串的請求。因此,在Action的name屬性中使用通配符后,可用一個<action>元素代替多個邏輯Action。以下是struts.xml配置文件中的代碼:<!--使用數(shù)字模式字符串定義Action的name,指定所有以Action結(jié)尾的請求,都可用LoginRegisteredAction來處理,method屬性使用{1}這個{1}代表進行模式匹配時第一個*所代替的字符串--><actionname="*Action"class="example.LoginRegistAction"method="{1}"><resultname="input">/login.jsp</result><resultname="error">/error.jsp</result><resultname="success">/welcome.jsp</result></action> 上面的<actionname="*Action".../>不是定義了一個普通Action,而是定義了一系列的邏輯Action——只要用戶請求的URL是*Action,action的模式,都可以使用該Action來處理。配置該action元素時,還指定method屬性(method屬性用于指定處理用戶請求的方法),但該method屬性使用了一個表達式{1},該表達式的值就是name屬性值中第一個*的值。例如,如果用戶請求的URL為loginAction.action,則調(diào)用example.LoginRegistAction類的login方法;如果請求URL為registAction.action,則調(diào)用example.LoginRegistAction類的regist方法。下面是本應(yīng)用所使用的LoginRegistAction類的代碼。publicclassLoginRegistActionextendsActionSupport{//封裝用戶請求參數(shù)的兩個屬性privateStringusername;privateStringpassword;//封裝處理結(jié)果的tip屬性privateStringtip;//username屬性對應(yīng)的setter和getter方法publicStringgetUsername(){returnusername;}publicvoidsetUsername(Stringusername){this.username=username;}//password屬性對應(yīng)的getter和setter方法publicStringgetPassword(){returnpassword;}publicvoidsetPassword(Stringpassword){this.password=password;}//tip屬性對應(yīng)的setter和getter方法publicStringgetTip(){returntip;}publicvoidsetTip(Stringtip){this.tip=tip;}//Action包含的注冊控制邏輯publicStringregist()throwsException{ActionContext.getContext().getSession().put("user",getUsername());setTip("恭喜您,"+getUsername()+",您已經(jīng)注冊成功!");returnSUCCESS;}//Action默認包含的控制邏輯publicStringlogin()throwsException{if(getUsername().equals("bruce")&&getPassword().equals("bruce")){ActionContext.getContext().getSession().put("user",getUsername());setTip("歡迎,"+getUsername()+",您已經(jīng)登錄成功!");returnSUCCESS;}else{returnERROR;}}}從上面程序的粗體字代碼中可以看出:該Action類不再包含默認的execute方法,而是包含了regist和login兩個方法,這兩個方法與execute方法簽名非常相似,只是方法名不同。同樣對于圖6-2所示的頁面,將JavaScript中regist函數(shù)修改為如下形式:functionregist(){//獲取頁面中第一個表單targetFrom=document.forms[0];//動態(tài)修改表單的Action屬性 targetForm.action="registAction.action";}在上面方法中看到,當(dāng)瀏覽者單擊“注冊”按鈕時,動態(tài)修改表單的Action屬性為registAction.Action,該請求匹配了*Action的模式,將交給該Action處理;registAction匹配*Action模式時,*的值為regist,則調(diào)用regist方法來處理用戶請求。除此之外,表達式也可出現(xiàn)在<action>元素的class屬性中,即Struts2允許將一系列的Action類配置成一個<action>元素,相當(dāng)于一個<action>元素配置了多個邏輯Action。以下是action.xml配置文件中的關(guān)鍵代碼:<!--使用數(shù)字模式字符串定義Action的name,指定所有以Action結(jié)尾的請求,都可用lexample.{1}Action來處理,這個{1}代表進行模式匹配時第一個*所代替的字符串--><actionname="*Action"class="example.{1}Action"><resultname="input">/login.jsp</result><resultname="error">/error.jsp</result><resultname="success">/welcome.jsp</result></action>上面<action>定義片段定義了一系列Action,這系列的Action名字應(yīng)該匹配*Action的模式,沒有指定method屬性,即默認使用execute方法來處理用戶請求。但class屬性值使用了表達式,上面配置片段的含義是,如果有URL為RegistAction.action的請求,將可以匹配*Action模式,交給該Action處理,其第一個“*”值為Regist,即該Action的處理類為example.RegistAction。類似地,如果有URL為LoginAction.action的請求,則處理類為example.LoginAction。為此,如果我們需要系統(tǒng)處理RegistAction和LoginAction兩個請求,則必須提供example.LoginAction和example.RegistAction兩個處理類。此時將如圖6-2所示頁面中的regist函數(shù)改為如下形式:functionregist(){//獲取JSP頁面中的一個表單元素targetForm=document.forms[0];//動態(tài)修改目標(biāo)表單的action屬性targetForm.action="RegistAction.action";}如果有需要,Struts2允許在class屬性和method屬性中同時使用表達式。見如下配置片段:<!--定義了一個action,同時在class屬性和method屬性中同時使用表達式--><actionname="*-*"method="{2}"class="action.{1}">上面的定義片段定義了一個模式為*-*的Action,即只要匹配該模式的請求,都可以被該Action處理。如果有URL為Book_save.action的請求,因為匹配了*-*模式,且第一個“*”的值為Book,第二個“*”的值為save,則意味著調(diào)用Book處理類的save方法來處理用戶請求。因為Struts2默認的校驗文件命名遵守如下規(guī)則:ActionName-validation.xml,即如果有類名為MyAction的Action類,則應(yīng)該提供名為MyAction-validation.xml的文件。但對于上面的<action>配置元素,class屬性值是一個表達式,這個表達式的值來自于前面Action的name屬性。例如,如果有URL為Book-save.action的請求,則該Action對應(yīng)的處理類為Book,對應(yīng)的數(shù)據(jù)校驗文件名為Book-validation.xml。實際上Struts2允許指定校驗文件時精確到處理方法,即指定如下形式的校驗文件:ActionName-methodName-validation.xml。所以對于Book-save.action的請求,系統(tǒng)將優(yōu)先使用Book-save-validation.xml校驗文件。即使對于class屬性值固定的Action,同樣可以為一個Action類指定多個校驗文件。見如下的Action配置片段:<!--配置了Action,指定了固定的class屬性,而method屬性使用表達式--><actionname="Crud_*"class="example.Crud"method="{1}">在上面的配置片段中,指定了該Action的實現(xiàn)類為example.Crud。該Action的name是一個模式字符串,則該Action將可以處理所有匹配Crud_*的請求。假設(shè)有URL為Crud_input的請求,該請求匹配了Crud_*的模式,故該Action的name可以處理該請求。對于該請求,Struts2將采用Crude_input-validation.xml校驗文件進行數(shù)據(jù)校驗。實際上,Struts2不僅允許在class屬性、name屬性中使用表達式,還允許在<action.../>元素的<result…/>子元素中使用表達式。下面提供了一個通用Action,該Action可以配置成如下形式:<!--定義一個通用Action--><actionname="*"><!--使用表達式定義Result><result>/{1}.jsp</result></action>在上面的Action定義中,Action的名字是一個“*”,即它可以匹配任意的Action,所有的用戶請求都可通過該Action來處理。因為沒有為該Action指定class屬性,即該Action使用ActionSupport作為處理類,而且因為該ActionSupport類的execute方法返回success字符串,即該Action總是直接返回result中指定JSP資源。JSP資源使用了表達式來生成資源名。上面Action定義的含義是:如果請求a.action,則進入a.jsp頁面;如果請求b.action,則進入b.jsp頁面。這種方式可以讓Struts2框架管理所有用戶請求,避免瀏覽者直接訪問系統(tǒng)JSP頁面。對于只是簡單的超級鏈接的請求,可以通過定義name為“*”的Action(該Action應(yīng)該放在最后定義)實現(xiàn)。除此之外,Struts2還允許在容器中定義一個默認的Action,當(dāng)用戶請求的URL在容器中找不到對應(yīng)的Action時,系統(tǒng)將使用默認的Action來處理用戶請求。現(xiàn)在的問題是,當(dāng)用戶請求的URL同時匹配多個Action時,應(yīng)使用哪個Action來處理用戶請求呢?假設(shè)有URL為abcAction.action的請求,在struts.xml文件中配置了如下3個Action,它們的Actionname的值分別為abcAction、*Action和*,則這個請求將被名為abcAction的Action處理。如果有URL為defAction.action的請求,struts.xml文件中同樣配置了abcAction、*Action和*這3個Action,那么defAction.action的請求顯然不會被name為abcAction的Action處理,但到底是被name="Action"的Action處理,還是被name="*"的Action處理呢?為了得到這個結(jié)果,我們做了一個natchSequence應(yīng)用。該應(yīng)用的struts.xml配置文件如下:<?xmlversion="1.0"encoding="GBK"?><!DOCTYPEstrutsPUBLIC"-//ApacheSoftwareFoundation//DTDStrutsConfiguration2.3//EN""/dtds/struts-2.3.dtd"><struts><packagename="default"extends="struts-default"><!--配置name="*"的第一個Action--><actionname="*"class="example.FirstAction"><resultname="success">/welcome.jsp</result></action><!--配置name="Action"的第二個Action--><actionname="*Action"class="example.TwoAction"><resultname="success">/welcome.jsp</result></action><!--配置name為LoginAction的第三個Action--><actionname="LoginAction"class="example.LoginAction"><resultname="input">/login.jsp</result><resultname="error">/error.jsp</result><resultname="success">/welcome.jsp</result></action></package></struts>上面配置文件中粗體字代碼包含了兩個支持模式匹配的Action,如果瀏覽器發(fā)出的URL為RegistAction.action的請求,該請求不是由第二個Action來處理,而是被第一個Action(即FirstAction類)處理的。將上面的struts.xml文件修改成如下形式:<?xmlversion="1.0"encoding="GBK"?><!DOCTYPEstrutsPUBLIC"-//ApacheSoftwareFoundation//DTDStrutsConfiguration2.3//EN""/dtds/struts-2.3.dtd"><struts><packagename="default"extends="struts-default"><!--配置name="*Action"的第一個Action--><actionname="*Action"class="example.TwoAction"><resultname="success">/welcome.jsp</result></action><!--配置name="*"的第二個Action--><actionname="*"class="example.FirstAction"><resultname="success">/welcome.jsp</result></action><!--配置name為LoginAction的第三個Action--><actionname="LoginAction"class="example.LoginAction"><resultname="input">/login.jsp</result>

<resultname="error">/error.jsp</result><resultname="success">/welcome.jsp</result></action></package></struts>同樣如果有RegistAction.action請求,則由TwoAction來處理。通過對比上面的配置文件,可以得出如下規(guī)律:假定有URL為abcAction.action的請求,如果struts.xml文件中有名為abcAction的Action,則一定由該Action來處理用戶請求;如果struts.xml文件中沒有名為abcAction的Action,則搜尋name屬性值能匹配abcAction的Action。例如name為*Action或*。注意,*Action并不會比*更優(yōu)先匹配abcAction的請求,而是先找到哪個Action,就由哪個Action來處理用戶請求。6.3配置處理結(jié)果6.3.1理解處理結(jié)果Action處理完用戶請求后,將返回一個普通字符串,整個普通字符串就是一個邏輯視圖名。Struts2通過配置邏輯視圖和物理視圖資源之間的映射關(guān)系,一旦系統(tǒng)收到Action返回的某個邏輯視圖名,系統(tǒng)就會把對應(yīng)的物理視圖呈現(xiàn)給瀏覽者。如圖6-4所示,Action處理完用戶請求后,并未直接將請求轉(zhuǎn)發(fā)給任何具體的視圖資源,而是返回一個邏輯視圖,Struts2框架收到這個邏輯視圖后,把請求轉(zhuǎn)發(fā)到對應(yīng)的視圖資源,視圖資源將處理結(jié)果呈現(xiàn)給用戶。相對Struts1框架而言,Struts2的邏輯視圖不再是ActionForward對象,而是一個普通字符串,這樣的設(shè)計更有利于將Action類與Struts2框架分離,提供了更好的代碼復(fù)用性。除此之外,Struts2還支持多種結(jié)果映射:Struts2框架將處理結(jié)果轉(zhuǎn)向?qū)嶋H資源時,實際資源不僅可以是JSP視圖資源,也可以是FreeMarker視圖資源,甚至可以將請求轉(zhuǎn)給下一個Action處理,形成Action的鏈?zhǔn)教幚怼?.3.2配置結(jié)果Struts2的Action處理用戶請求結(jié)束后,返回一個普通字符串——邏輯視圖名,必須在struts.xml文件中完成邏輯視圖和物理視圖資源之間的映射關(guān)系,才可以讓系統(tǒng)轉(zhuǎn)到實際視圖資源。簡單地說,配置結(jié)果是告訴Struts2框架:當(dāng)Action處理結(jié)束時,系統(tǒng)下一步將做什么,系統(tǒng)下一步應(yīng)該調(diào)用哪個物理視圖資源來顯示處理結(jié)果。Struts2在struts.xml文件中使用<result>元素所在的位置不同,Struts2提供了兩種結(jié)果。局部結(jié)果:將<result>作為<action>元素的子元素配置。全局結(jié)果:將<result>作為<global-results>元素的子元素配置。全局結(jié)果將在后面進行介紹,本節(jié)只介紹局部結(jié)果。局部結(jié)果是通過在<action>元素定義<result>子元素進行配置的,一個<action>元素可以有多個<result>子元素,這表示一個Action可以對應(yīng)多個結(jié)果。配置<result>元素時通常需要指定如下兩個屬性:name:該屬性指定所配置的邏輯視圖名。type:該屬性指定結(jié)果類型。最典型的<result>配置片段如下:<actionname="Login"class="example.LoginAction"><!--為success的邏輯視圖配置Result,type屬性指定結(jié)果類型--><resultname="success"type="dispatcher"><!--指定該邏輯視圖對應(yīng)的實際視圖資源--><paramname="location">/thank_you.jsp</param></result></action>上面的<result>元素使用了最煩瑣的形式,既指定了需要映射的邏輯視圖名(success),也指定了結(jié)果類型(dispatcher),并使用子元素的形式來指定實際視圖資源。上面的粗體字代碼指定:當(dāng)Action返回名為“success”的邏輯視圖名時,系統(tǒng)將轉(zhuǎn)到thank_you.jsp頁面。對于上面使用<param>子元素配置結(jié)果的形式,其中<param>元素配置的參數(shù)名由name屬性指定,此處的name屬性可以為如下兩個值:location:參數(shù)指定了邏輯視圖所對應(yīng)的實際視圖資源。parse:該參數(shù)指定是否允許在實際視圖名字中使用OGNL表達式,其參數(shù)值默認為true。如果設(shè)置該參數(shù)值為false,則不允許在實際視圖名中使用表達式。通常無須修改該屬性值。因為通常無須指定parse參數(shù)的值,所以常采用如下簡化形式來配置實際視圖資源:<actionname="Login"class="example.LoginAction"><!--為success的邏輯視圖配置Result,type屬性指定結(jié)果類型--><resultname="success"type="dispatcher">/thank_you.jsp</result></action>除此之外,Struts2還允許省略指定結(jié)果類型,即可改寫成如下形式:<actionname="Login"class="example.LoginAction"><!--為success的邏輯視圖配置Result,省略type屬性--><resultname="success">/thank_you.jsp</result></action>在這個時候,系統(tǒng)將使用默認的結(jié)果類型。Struts2默認的結(jié)果類型就是dispatcher(用于JSP整合的結(jié)果類型)。不僅如此,Struts2還可以省略邏輯視圖名,即改寫成如下形式:<actionname="Login"class="example.LoginAction"><!--配置默認結(jié)果,省略type屬性--><result>/thank_you.jsp</result></action>如果省略了<result…/>元素的name屬性,則系統(tǒng)采用默認的name屬性值。默認的name屬性值為success。因此,即使不給出邏輯視圖名success,系統(tǒng)也一樣會為success邏輯視圖配置結(jié)果。6.3.3Struts2支持的結(jié)果類型Struts2支持使用多種視圖技術(shù),如JSP、Velocity和FreeMarker等。當(dāng)一個Action處理用戶請求結(jié)束后僅返回一個字符串,這個字符串是邏輯視圖名。直到在struts.xml文件中配置物理邏輯視圖資源之前,該邏輯視圖均未與任何的視圖技術(shù)及任何的視圖資源關(guān)聯(lián)。結(jié)果類型決定了Action處理結(jié)束后將調(diào)用哪種視圖資源來呈現(xiàn)處理結(jié)果。Struts2的結(jié)果類型要求實現(xiàn)com.opensymphony.xwork2.Result,這個結(jié)果是所有結(jié)果類型的通用接口。如果需要自己的結(jié)果類型,則需提供一個實現(xiàn)該接口的類,并且在struts.xml文件中配置該結(jié)果類型。Struts2默認提供了一系列的結(jié)果類型,下面是struts-default.xml配置文件的配置片段:<!--配置系統(tǒng)支持的結(jié)果類型--><result-types><!--Action鏈?zhǔn)?/p>

溫馨提示

  • 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)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論