Struts2第三天。如果老張他喜歡頭發,他肯定會把頭上的頭發有多少根,一根一根的數出來。他搞的太細了!
今天的重點內容是國際化、表單與Action數據交互、表單校驗,不多說了開始總結。
一、Struts2國際化
在我們學習WEB基礎的時候就講到了國際化,Struts2中的國際化實現方式與我們之前所學習到的國際化相同。但是Struts2中對國際化做了強化支持!
我們通過在struts.xml文件中加入”<constant name="struts.custom.i18n.resources" value="*.properties"></constant>”為指定全局國際化資源文件。Struts2會根據瀏覽器設置的語言信息運行對應的國際化文件,如果沒找到就根據操作系統的語言查找指定的文件,還是沒有,那就使用默認的。我們必須在struts.xml中使用定義在struts-default.xml文件中的defaultStack攔截器堆棧。使用defaultStack我們必須在package中添加extends="struts-default"屬性。如果在我們的Action中沒有使用任何攔截器,defaultStack默認被使用。如果有使用任何其他攔截器,我們必須手動加入defaultStack攔截器堆棧。Struts2將使用defaultStack攔截器堆棧中的i18n攔截器,為我們提供國際化支持。
引入多個全局資源包的方法是在上面的value屬性中添加以”,”分隔的多個資源文件。排在最后的資源包的優先級別最高(如果有重復的資源名稱)。那如果有時我想在JSP頁面中使用第一個資源包中的資源怎么辦?Struts2為我們提供了一個標簽“<s:i18n name="first.properties"></s:i18n>”,在標簽體內使用到的國際化資源,全以first.properties為先。
我們可以為每個Action指定一個資源包,資源包的名稱與Action的名稱相同。Struts2的國際化模塊會先找與Action對應的資源包,如果沒有就找它上一級的資源包,就這樣逐級向上。如果直到類所在包的是后一層目錄也沒找到就使用全局資源。這有什么好處?我們可能會有多個Action使用同一個或多個相同的資源,難道我們要在每個Action對應的資源包里定義它嗎?當然不需要,我們只需要把它定義在這幾個Action的上級且同一目錄即可。
我們如何在JSP頁面有使用國際化資源?Struts2的tags為我們提供了“<s:text name=""></s:text>”標簽,它是專門用來訪問國際化資源的。除此之外我們也可以使用“<s:property value=”getText(key)”>”,這個getText()是哪來的?當然是ValueStack中的某個對象的方法嘍!是類型為com.opensymphony.xwork2.DefaultTextProvider對象的。Struts2中使用OGNL操作ValueStack和ContextMap。OGNL看到getText(key)時,它會在ValueStack中從上向上反射每一個對象,如果哪一個對象最先具有這個方法,則OGNL就調用這個對象的getText(key)方法。
除了在JSP頁面中需要使用到國際化資源,我們在Action中也需要使用國際化資源。此時,我們需要將我們的Action類繼承自ActionSupport類,它實現了專門用于操作國際化的接口TextProvider。ActionSupport還實現了其他非常有用的接口,我們在下面會總結。此后,我們只需要調用getText()方法,即可獲得相應的資源信息。我們的Action也可以繼承自DefaultTextProvider類,但它默認情況下去搜索全局資源包,不會找Action的資源包。而ActionSUpport正如我們在上面所說,以Action的資源包優先級最高...。
我們知道我們可以為國際化資源指定參數,比如“regNameError={0} is invalid.”。我們在JSP頁面中可以通過<s:param></s:param>標簽來指定,如:
<s:text name=”regNameError”> <s:param></s:param> </s:text> |
或<s:text name=”getText('regNameError','xxx')”></s:text>。在Action中直接使用getText(“regNameError”,”xxx”)。
我們之所以能夠如此方便的使用國際化支持,JDK中的java.util.Locale為此做了很大的貢獻。目前我們使用國際化操作,無不基于java.util.Locale。因為OGNL的強大,我們也可以在JSP頁面中使用java.util.Locale還記得嗎?在OGNL中調用XXX類的靜態方法或成員的方式,比如調用java.util.Locale的getCountry():<s:property value=”@java.util.Locale@getDefault()”/>。
二、表單與Action數據交互
相比Struts1,在Strut2中的一大變化是我們不需要ActionForm了。我們在使用Struts1時,為了操作表單數據,我們需要額外定義一個繼承自ActionForm的FormBean。然后再將FormBean中的數據Copy到Bean中。
Struts2是如何實現對表單數據的操作呢?Struts2的ValueStack一直發輝著它的作用,ValueStack像是能完成Struts2的在所在操作,上面的國際化也是使用的ValueStack存儲的。在Struts2中操作表單數據,我們需要在我們Action定義屬性。在Action添加的屬性可以是基本數據類型也可以是復合類型。
進行表單與Action數據交互時,我們的Action類無需實現任何接口或繼承自任何類。但是,我們必須在struts.xml中使用定義在struts-default.xml文件中的defaultStack攔截器堆棧。使用defaultStack我們必須在package中添加extends="struts-default"屬性。如果在我們的Action中沒有使用任何攔截器,defaultStack默認被使用。如果有使用任何其他攔截器,我們必須手動加入defaultStack攔截器堆棧。
Struts2正是使用在defaultStack中的params攔截器,來為我們的Action設置屬性值。如何使用基本類型屬性和復合類型屬性與JSP頁面交互呢?比如在我們的RegUserAction中有一個User屬性和一個字符串型的password2屬性。那么我們在JSP頁面中應該這樣使用:
<s:form action=”RegUserAction”> <s:textfield name=”user.name”/> <s:textfield name=”user.password”/> <s:textfield name=”user.email”/> <s:textfield name=”password2”/> <s:submit value=”注冊”></s:submit> </s:form> |
點擊注冊按鈕后,Struts2正是使用params攔截器將數據設置到RegUserAction的屬性中。
因為這些表單字段數據是被保存在ValueStack中,所以我們在JSP頁面我們可以使用EL表達試,如:${user.name},也可以使用OGNL表達式,如:<s:property value=”user.name”/>來獲取數據。
除此之外,我們可以讓Action實現ModelDriven接口,并將User做為它的泛型參數。如果被ModelDriven接管的實體類型中有與我們的Action屬性相同的,ModelDriven的優先級高。Struts2會設置ModelDriven接管的實體類型的是屬性,而忽略Action的同名屬性。但這并不會引起錯誤,因為我們的數據全部放在ValueStack中,使用OGNL可以正確獲取。我們不推薦使用ModelDriven。
三、表單校驗
表單校驗在Struts2中實現比較簡單,表單數據的校驗分為前臺校驗和后臺校驗。同樣我們需要開啟defaultStack攔截器堆棧,首先我們來看看后臺校驗。
后臺校驗,我們的Action可以繼承ValidationAwareSupport類和實現Validateable接口。因為我們同時需要在類中使用到國際化表單校驗,所以我們可以直接繼承ActionSupport類。Action類需要實現validate方法。
在validate方法中進行Action的屬性校驗,并且我們可以調用ActionSupport類的addActionError(String)方法,添加錯誤信息。我們可以在這里使用國際化支持,而在JSP頁面中需要使用<s:fieldError>取出所有錯誤信息,或者指定字段名而取出某個字段的錯誤信息。
但有一個問題,一個Action類可以有多個方法分別用于處理不同的請求。Struts2每當調用其中一個方法時都會進行表單校驗,這沒必要啊!所以我們在不需要進行表單校驗的方法上添加“@SkipValiation”注解,這樣就會被Struts2過濾掉。
我們也可以添加”ActionClassName-validation.xml”配置文件,來為指定名稱的Action(ActionClassName)添加表單校驗。具體的配置可以參看struts2包中所帶的例子程序。我們也可以使用“ActionClassName-actionname-validation.xml”來為Action類中的某個具體方法指定表單校驗。
前臺校驗,前臺校驗的好處不再說明了。前提我們以配置文件的方式為Action指定的表單校驗,那么在JSP頁面中,我們可以直接引用配置文件中的數據,實現前臺校驗。Struts2中的struts-tags為我們提供的表單標簽中可以引用配置文件中對應的校驗數據。在我們訪問到某個JSP頁面時,Struts2的標簽會為我們自動生成相應的JavaScript代碼,但Struts2的表單前臺校驗的這種功能還不夠強大。在此就不多做總結了。
老張講得比較細致,我也僅僅是泛泛而總結。按照正常的進程,我們明天還有一天的Struts2課程,但由于時間不夠,老張決定哪天同學們休息時再為我們補一天,太好了!