Java程序员从笨鸟到菜鸟之(四十四)细谈struts2(七)数据类型转换详解
?本文來(lái)自:曹勝歡博客專(zhuān)欄。轉(zhuǎn)載請(qǐng)注明出處:http://blog.csdn.net/csh624366188
?
???????? Web應(yīng)用程序的交互都是建立在HTTP之上的,互相傳遞的都是字符串。也就是說(shuō)服務(wù)器接收到的來(lái)自用戶的數(shù)據(jù)只能是字符串或者是字符數(shù)組,而在Web應(yīng)用的對(duì)象中,往往使用了多種不同的類(lèi)型,如整數(shù)(int)、浮點(diǎn)數(shù)(float)、日期(Date)或者是自定義數(shù)據(jù)類(lèi)型等。因此在服務(wù)器端必須將字符串轉(zhuǎn)換成合適的數(shù)據(jù)類(lèi)型。
???????? Struts2框架中為我們提供了一些簡(jiǎn)單類(lèi)型的轉(zhuǎn)換器,比如轉(zhuǎn)換為int、float等簡(jiǎn)單數(shù)據(jù)類(lèi)型是不需要我們自己定義轉(zhuǎn)換器去轉(zhuǎn)換的,struts2內(nèi)部本身就為我們提供了轉(zhuǎn)換的方法,但像一些復(fù)雜的類(lèi)型和我們自定義的數(shù)據(jù)類(lèi)型還是需要我們自己去寫(xiě)轉(zhuǎn)換器去轉(zhuǎn)換的。在轉(zhuǎn)換工程中,如果在類(lèi)型轉(zhuǎn)換中出現(xiàn)異常,類(lèi)型轉(zhuǎn)換器開(kāi)發(fā)者無(wú)需關(guān)心異常處理邏輯,Struts2的conversionError攔截器會(huì)自動(dòng)處理該異常,并且提示在頁(yè)面上生成提示信息。
下面我們就一步步的實(shí)現(xiàn)和注冊(cè)一個(gè)我們自己的轉(zhuǎn)換器,也就是自定義類(lèi)型轉(zhuǎn)換器的幾個(gè)步驟:
一:自定義類(lèi)型轉(zhuǎn)換器
實(shí)現(xiàn)自定義類(lèi)型轉(zhuǎn)換器我們一般有兩種方式:
1.實(shí)現(xiàn)OGNL提供的TypeConvert接口以及實(shí)現(xiàn)了TypeConvert接口的DefaultTypeConvert類(lèi)來(lái)實(shí)現(xiàn)自定義的類(lèi)型轉(zhuǎn)換器。我們來(lái)看一下DefaultTypeConvert類(lèi)的源碼:
?
publicclass DefaultTypeConverter implements TypeConverter{ public DefaultTypeConverter(){ super(); } /** * @param context:類(lèi)型轉(zhuǎn)換的上下文 * @param value:需要轉(zhuǎn)換的參數(shù) * @param toType:轉(zhuǎn)換后的目的類(lèi)型 */ public Object convertValue(Map context, Object value, Class toType) { return OgnlOps.convertValue(value, toType); } public Object convertValue(Map context, Object target, Member member, String propertyName, Object value, Class toType) { return convertValue(context, value, toType); } }convertValue方法的作用:
該方法負(fù)責(zé)完成類(lèi)型的雙向轉(zhuǎn)換,為了實(shí)現(xiàn)雙向轉(zhuǎn)換,我們通過(guò)判斷toType的類(lèi)型即可判斷轉(zhuǎn)換的方向。toType類(lèi)型是需要轉(zhuǎn)換的目標(biāo)類(lèi)型,如:當(dāng)toType類(lèi)型是User類(lèi)型時(shí),表明需要將字符串轉(zhuǎn)換成User實(shí)例;當(dāng)toType類(lèi)型是String類(lèi)型時(shí),表明需要把User實(shí)例轉(zhuǎn)換成字符串類(lèi)型。通過(guò)toType類(lèi)型判斷了類(lèi)型轉(zhuǎn)換的方向后,我們就可以分別實(shí)現(xiàn)兩個(gè)方向的轉(zhuǎn)換邏輯了。實(shí)現(xiàn)類(lèi)型轉(zhuǎn)換器的關(guān)鍵就是實(shí)現(xiàn)conertValue方法,該方法有三個(gè)參數(shù):
第一個(gè)參數(shù) context:類(lèi)型轉(zhuǎn)換的上下文
第二個(gè)參數(shù) value:需要轉(zhuǎn)換的參數(shù)
第三個(gè)參數(shù) toType:轉(zhuǎn)換后的目的類(lèi)型
?
2. 基于Struts2的類(lèi)型轉(zhuǎn)換器
Struts 2提供了一個(gè)StrutsTypeConverter的抽象類(lèi),這個(gè)抽象類(lèi)是DefaultTypeConverter類(lèi)的子類(lèi)。開(kāi)發(fā)時(shí)可以直接繼承這個(gè)類(lèi)來(lái)進(jìn)行轉(zhuǎn)換器的構(gòu)建。通過(guò)繼承該類(lèi)來(lái)構(gòu)建類(lèi)型轉(zhuǎn)換器,可以不用對(duì)轉(zhuǎn)換的類(lèi)型進(jìn)行判斷(和第一種方式的區(qū)別),下面我們來(lái)看一下StrutsTypeConverter類(lèi)的源碼:
publicabstractclass StrutsTypeConverter extends DefaultTypeConverter { //重寫(xiě)DefaultTypeConverter類(lèi)的convertValue方法 public Object convertValue(Map context, Object o, Class toClass) { //如果需要把復(fù)合類(lèi)型轉(zhuǎn)換成字符串類(lèi)型 if (toClass.equals(String.class)) { return convertToString(context, o); } //如果需要把字符串轉(zhuǎn)換成符合類(lèi)型 elseif (o instanceof String[]) { return convertFromString(context, (String[]) o, toClass); } //如果需要把字符串轉(zhuǎn)換成符合類(lèi)型 elseif (o instanceof String) { return convertFromString( context, new String[]{(String) o}, toClass); } else { return performFallbackConversion(context, o, toClass); } } protected Object performFallbackConversion(Map context, Object o, Class toClass) { returnsuper.convertValue(context, o, toClass); } publicabstract Object convertFromString(Map context, String[] values, Class toClass); publicabstract String convertToString(Map context, Object o); }??? 該類(lèi)已經(jīng)實(shí)現(xiàn)了DefaultTypeConverter的convertValue方法。實(shí)現(xiàn)該方法時(shí),它將兩個(gè)不同轉(zhuǎn)換方向替換成不同方法——當(dāng)需要把字符串轉(zhuǎn)換成復(fù)合類(lèi)型時(shí),調(diào)用convertFromString抽象方法;當(dāng)需要把復(fù)合類(lèi)型轉(zhuǎn)換成字符串時(shí),調(diào)用convertToString抽象方法,下圖展示了其對(duì)應(yīng)關(guān)系:
?
二.注冊(cè)自定義類(lèi)型轉(zhuǎn)換器:
實(shí)現(xiàn)了自定義的類(lèi)型轉(zhuǎn)換器之后,將該類(lèi)型轉(zhuǎn)換器注冊(cè)在Web應(yīng)用中,Struts2框架才可以正常使用該類(lèi)型轉(zhuǎn)換器,類(lèi)型轉(zhuǎn)換器的注冊(cè)分為兩種,
1.注冊(cè)局部類(lèi)型轉(zhuǎn)換器。
局部類(lèi)型轉(zhuǎn)換器僅僅對(duì)某個(gè)Action起作用。局部類(lèi)型轉(zhuǎn)換器非常簡(jiǎn)單,只需要在相應(yīng)的Action目錄下新建一個(gè)資源文件。該資源文件名格式如下。ActionName-conversion.properties。其中ActionName表示需要進(jìn)行轉(zhuǎn)換的Action的類(lèi)名,“-conversion.properties”字符串則是固定格式的。該文件也是一個(gè)典型Properties文件,文件由鍵值對(duì)組成:propertyName = 類(lèi)型轉(zhuǎn)換器類(lèi)
如:name=util.NameConvert
name:表示要進(jìn)行轉(zhuǎn)換的屬性
util.NameConvert:表示要進(jìn)行轉(zhuǎn)換的自定義類(lèi)型轉(zhuǎn)換器。
注意:該屬性文件應(yīng)該與ActionName.class放在相同位置。
??
2.注冊(cè)全局類(lèi)型轉(zhuǎn)換器。對(duì)所有Action的特定類(lèi)型的屬性都會(huì)生效。
?? ????????全局類(lèi)型轉(zhuǎn)換器,必須提供一個(gè)xwork-conversion.properties文件。文件必須保存在classes目錄下。該資源文件名格式如下:
? ???復(fù)合類(lèi)型=對(duì)應(yīng)的類(lèi)型轉(zhuǎn)換器?
???? 復(fù)合類(lèi)型:指定需要完成類(lèi)型轉(zhuǎn)換的復(fù)合類(lèi)
?? ??對(duì)應(yīng)的類(lèi)型轉(zhuǎn)換器:指定所指定類(lèi)型轉(zhuǎn)換的轉(zhuǎn)換器。
?如:注冊(cè)User類(lèi)的全局類(lèi)型轉(zhuǎn)換器為:UserConverter
???? cn.wjz.bean.User = cn.wjz.util.UserConverter
?
注意:如果局部類(lèi)型轉(zhuǎn)換和全局類(lèi)型轉(zhuǎn)換同時(shí)存在的話,局部類(lèi)型轉(zhuǎn)換具有較高的優(yōu)先級(jí),也就是以局部類(lèi)型轉(zhuǎn)換器為主。
三.集合類(lèi)型的類(lèi)型轉(zhuǎn)換
對(duì)于List元素來(lái)說(shuō),內(nèi)容如: Element_attributeName=typeName;
對(duì)于Map元素來(lái)說(shuō),
(1)如果表示key的類(lèi)型,則:Key_attributeName=typeName;
(2)如果表示value的類(lèi)型,則為:Element_attributeName=typeName;
?
比如,此處沒(méi)有使用泛型,而是使用了局部類(lèi)型轉(zhuǎn)換文件:
Conversion02Action.java public class Conversion02Action extends ActionSupport { private List lists; private Map maps; public String execute()throws Exception{ System.out.println(((Person)lists.get(0)).getGender()); System.out.println(((Person)lists.get(0)).getSalary()); System.out.println(((Person)maps.get("one")).getGender()); System.out.println(((Person)maps.get("one")).getSalary()); return SUCCESS; } public List getLists() { return lists; } public void setLists(List lists) { this.lists = lists; } public Map getMaps() { return maps; } public void setMaps(Map maps) { this.maps = maps; } }
Conversion02Action-conversion.properties
?
Element_lists=org.person.Person Key_maps=java.lang.String Element_maps=org.person.Person
?頁(yè)面表單:
<s:fielderror></s:fielderror> <s:form action="conversion02" > <s:textfield label="list1.salary" name="lists[0].salary"></s:textfield> <s:textfield label="list1.gender" name="lists[0].gender"></s:textfield> <s:textfield label="map1.gender" name="maps['one'].gender"></s:textfield> <s:textfield label="map1.salary" name="maps['one'].salary"></s:textfield> <s:submit value="提交"></s:submit> </s:form>
四.Struts 2內(nèi)建的類(lèi)型轉(zhuǎn)換器 :
?? Sturts 2為常用的數(shù)據(jù)類(lèi)型提供了內(nèi)建的類(lèi)型轉(zhuǎn)換器,所以根本不用自定義轉(zhuǎn)換器。對(duì)于內(nèi)建的轉(zhuǎn)換器,Struts在遇到這些類(lèi)型時(shí),會(huì)自動(dòng)去調(diào)用相應(yīng)的轉(zhuǎn)換器進(jìn)行類(lèi)型轉(zhuǎn)換。
Struts 2全部的內(nèi)建轉(zhuǎn)換器:
?? ·基本數(shù)據(jù)類(lèi)型以及其封裝類(lèi)。包括:boolean和Boolean、char和Character、int和Integer、long和Integer、float和Float、double和Double。完成字符串和基本數(shù)據(jù)類(lèi)型或其封裝類(lèi)之間的轉(zhuǎn)換。
?? ·日期類(lèi)型。使用當(dāng)前區(qū)域的短格式轉(zhuǎn)換,即DateFormat.getInstance(DateFormat.SHORT)完成字符串和日期類(lèi)型之間的轉(zhuǎn)換。
?? ·集合(Collection)類(lèi)型。將request.getParameterValues(String arg)返回的字符串?dāng)?shù)據(jù)與java.util.Collection轉(zhuǎn)換。集合元素為String類(lèi)型。
?? ·集合(Set)類(lèi)型。與Collection的轉(zhuǎn)換相似,只是去掉了相同的值。集合元素為String類(lèi)型。
?? ·數(shù)組類(lèi)型。將request.getParameterValues(String arg)返回的字符串?dāng)?shù)組中的每個(gè)字符串值取出組成一個(gè)數(shù)組。數(shù)組元素為String類(lèi)型。
注意:Struts 2提供的全部?jī)?nèi)建轉(zhuǎn)換器都是雙向的,也就是說(shuō)從用戶輸入頁(yè)到服務(wù)器端時(shí)會(huì)將字符串類(lèi)型轉(zhuǎn)換成相應(yīng)的數(shù)據(jù)類(lèi)型。在顯示輸出時(shí),又會(huì)將相應(yīng)的數(shù)據(jù)類(lèi)型轉(zhuǎn)換成字符串類(lèi)型來(lái)顯
數(shù)組類(lèi)型的轉(zhuǎn)換器。這個(gè)轉(zhuǎn)換器非常有用,比如多個(gè)表單元素的name屬性相同,那么提交的參數(shù)就不再是字符串而是一個(gè)字符串?dāng)?shù)組。通過(guò)Sturts 2提供的數(shù)組類(lèi)型的轉(zhuǎn)換器就能很方便的將多個(gè)相同name屬性的表單元素的值封裝到Action中的一個(gè)數(shù)組中。
五.類(lèi)型轉(zhuǎn)換中錯(cuò)誤處理:
1.類(lèi)型轉(zhuǎn)換的錯(cuò)誤處理流程:
Struts2提供了一個(gè)名為conversionError的攔截器,這個(gè)攔截器被注冊(cè)在默認(rèn)的攔截器棧中,在Struts-default.xml中的配置信息:
<interceptor-stack name="defaultStack"> .. .. .. <!—- 處理類(lèi)型轉(zhuǎn)換錯(cuò)誤的攔截器 --> <interceptor-ref name="conversionError"/> <!—- 處理數(shù)據(jù)校驗(yàn)的攔截器 --> <interceptor-ref name="validation"> <param name="excludeMethods">input,back,cancel,browse</param> </interceptor-ref> <interceptor-ref name="workflow"> <param name="excludeMethods">input,back,cancel,browse</param> </interceptor-ref> </interceptor-stack>
如果Struts2的類(lèi)型轉(zhuǎn)換器執(zhí)行類(lèi)型轉(zhuǎn)換時(shí)出現(xiàn)錯(cuò)誤,該攔截器將負(fù)責(zé)將對(duì)應(yīng)的錯(cuò)誤封裝成表單域錯(cuò)誤(fieldError),并將這些錯(cuò)誤信息放入ActionContext中。
Struts2的錯(cuò)誤處理流程:
????????????????????????????????????? ?
2、錯(cuò)誤信息的友好顯示
在進(jìn)行類(lèi)型轉(zhuǎn)換中,如果出現(xiàn)錯(cuò)誤將會(huì)提示錯(cuò)誤信息。Struts 2默認(rèn)提供了錯(cuò)誤信息提示,但是這些錯(cuò)誤信息提示不夠友好,下面將介紹如何自定義錯(cuò)誤信息來(lái)取代Struts 2的默認(rèn)錯(cuò)誤信息。
·定義全局類(lèi)型轉(zhuǎn)換錯(cuò)誤處理信息:
?在應(yīng)用的國(guó)際化資源文件中增加如下的信息:
?xwork.default.invalid.fieldvalue = key
key的值就是用戶希望在頁(yè)面中顯示的提示信息。? 例如:
| #改變默認(rèn)的類(lèi)型轉(zhuǎn)換失敗后的提示信息 xwork.default.invalid.fieldvalue = {0}字段類(lèi)型轉(zhuǎn)換失敗!! 因?yàn)榘俏鳉W字符,因此使用 native2ascii 命令處理 xwork.default.invalid.fieldvalue = ?{0}\u5b57\u6bb5\u7c7b\u578b\u8f6c\u6362\u5931\u8d25\uff01\uff01 |
?
·定義局部類(lèi)型轉(zhuǎn)換錯(cuò)誤處理信息:
?在某些時(shí)候可能還需要對(duì)特定的字段指定特別的提示信息,此時(shí)可以提供該Action的局部資源文件,文件名:ActionName.properties , 在文件中增加如下一項(xiàng):
???? invalid.fieldvalue.屬性名 =提示信息
? 例如:
| #改變Action中birth屬性類(lèi)型轉(zhuǎn)換錯(cuò)誤后的提示信息 invalid.fieldvalue.birth = 生日信息必須滿足yyyy-MM-DD格式 使用 native2ascii 命令處理 invalid.fieldvalue.birth = \u751f\u65e5\u4fe1\u606f\u5fc5\u987b\u6ee1 \u8db3yyyy-MM-DD\u683c\u5f0f ? |
?
六.類(lèi)型轉(zhuǎn)換的流程
?1、用戶進(jìn)行請(qǐng)求,根據(jù)請(qǐng)求名在struts.xml中尋找Action
?2、在Action中,根據(jù)請(qǐng)求域中的名字去尋找對(duì)應(yīng)的set方法。找到后在賦值之前會(huì)檢查這個(gè)屬性有沒(méi)有自定義的類(lèi)型轉(zhuǎn)換。沒(méi)有的話,按照默認(rèn)進(jìn)行轉(zhuǎn)換;如果某個(gè)屬性已經(jīng)定義好了類(lèi)型轉(zhuǎn)換,則會(huì)去檢查在Action同一目錄下的action文件名-conversion.properties文件。
?3、從文件中找到要轉(zhuǎn)換的屬性及其轉(zhuǎn)換類(lèi)。
?4、然后進(jìn)入轉(zhuǎn)換類(lèi)中,在此類(lèi)中判斷轉(zhuǎn)換的方向。我們是先從用戶請(qǐng)求開(kāi)始的,所以這時(shí)先進(jìn)入從字符串到類(lèi)的轉(zhuǎn)換。返回轉(zhuǎn)換后的對(duì)象。流程返回Action。
?5、將返回的對(duì)象賦值給Action中的屬性,執(zhí)行Action中的execute()
?6、執(zhí)行完execute()方法,根據(jù)struts.xml的配置轉(zhuǎn)向頁(yè)面
?7、在jsp中顯示內(nèi)容時(shí),根據(jù)頁(yè)面中的屬性名去調(diào)用相應(yīng)的get方法,以便輸出
?8、在調(diào)用get方法之前,會(huì)檢查有沒(méi)有此屬性的自定義類(lèi)型轉(zhuǎn)換。如果有,再次跳轉(zhuǎn)到轉(zhuǎn)換類(lèi)當(dāng)中。
?9、在轉(zhuǎn)換類(lèi)中再次判斷轉(zhuǎn)換方向,進(jìn)入由類(lèi)到字符串的轉(zhuǎn)換,完成轉(zhuǎn)換后返回字符串。
?10、將返回的值直接帶出到要展示的頁(yè)面當(dāng)中去展示。
?
轉(zhuǎn)載于:https://blog.51cto.com/javacsh/1129225
總結(jié)
以上是生活随笔為你收集整理的Java程序员从笨鸟到菜鸟之(四十四)细谈struts2(七)数据类型转换详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java - 流
- 下一篇: linux命令:xargs