Struts2之类型转换
http://blog.csdn.net/xiazdong/article/details/7229682
一、Struts2 類型轉換介紹
?
類型轉換:解析HTTP請求參數,將Http請求參數賦值給Action的屬性;比如:
?
[html] <s:form action="valid" > <s:textfield label="用戶名" name="name"></s:textfield> <s:password label="密碼" name="password"></s:password> ? <s:textfield label="年齡" name="age"></s:textfield> ? <s:submit value="提交"></s:submit> </s:form>
 
此處將名為name、password、age的值賦值給Action的屬性,類型轉換是指這個賦值過程中可能出現的類型不一致問題而做出的轉換,因為HTTP參數都是字符串類型的;因此從String類型的age參數傳給int類型的age屬性時,就需要類型轉換,當然這些struts2框架已經做完了,開發人員不需要自行處理;
Struts2已經內建了對于String和基本類型的類型轉換,比如String<-->int 、String<-->boolean等;
Action屬性一定要有getter和setter方法!?
Struts2提供了強大的類型轉換支持,不僅提供了內置的類型轉換器,還可以自定義類型轉換器,以滿足自定義需求;
Struts2類型轉換是通過 params攔截器進行轉換;如果轉換失敗,則 conversionError攔截器攔截該異常,并封裝到fieldError中,放入ActionContext中;
Struts2類型轉換還支持OGNL表達式,只需要在表單控件的name屬性使用ognl表達式即可,比如表單控件的name屬性為user.name,則此控件的數據將進入賦值給Action的user屬性中的name屬性;
?
二、通過一個例子初步了解Struts2類型轉換
此處的類型轉換因為是內建的,因此代碼上和原來的struts2應用沒有不同,struts2框架內部完成了所有了類型轉換,以下程序是將name、age賦值給Action類的name、age屬性,gender、salary賦值給p.gender、p.salary屬性;struts.xml的配置和原來一樣,所以就不給出了;
Conversion01Action.java
[java] package org.conversion.action;import org.person.Person;import com.opensymphony.xwork2.ActionSupport;public class Conversion01Action extends ActionSupport {private String name;private int age;private Person p ;public String execute()throws Exception{System.out.println(name);System.out.println(age);System.out.println(p.getGender());System.out.println(p.getSalary());return SUCCESS;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public Person getP() {return p;}public void setP(Person p) {this.p = p;}}
1.jsp
此處需要注意的是性別、薪水的表單控件的name屬性是OGNL表達式;
[html]<%@ page language="java" contentType="text/html; charset=utf-8"pageEncoding="utf-8"%><%@taglib prefix="s" uri="/struts-tags" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Insert title here</title> </head> <body> <s:fielderror></s:fielderror><s:form action="conversion01" ><s:textfield label="姓名" name="name"></s:textfield><s:textfield label="年齡" name="age"></s:textfield><s:textfield label="性別" name="p.gender"></s:textfield><s:textfield label="薪水" name="p.salary"></s:textfield><s:submit value="提交"></s:submit></s:form> </body> </html>
補充:List 和 Map 的Action屬性的類型轉換問題
前面我們將的都是基本類型和自定義類型,因此這里我們將講述集合類型的類型轉換問題; 如果Action的屬性為List類型,List<String>lists ,則表單控件的命名方式為 lists[i] ,如 lists[0]表示第1個元素; 如果Action的屬性為Map類型,Map<String,Person> maps;則表單控件的命名方式為maps[ ' first ' ].salary ,表示map中key為'first'的value中的salary屬性;
以上的list和map類型屬性都通過泛型的方式說明集合元素的類型,如果在JDK1.5之前,泛型沒有出現,則需要通過局部類型轉換文件進行表示;
局部類型轉換文件:對于特定Action的特定屬性有效,位于特定Action同一目錄下,命名規則:?ActionName-conversion.properties;
對于List元素來說,內容如 : Element_attributeName=typeName; 對于Map元素來說, (1)如果表示key的類型,則:Key_attributeName=typeName; (2)如果表示value的類型,則為:Element_attributeName=typeName;
比如,此處沒有使用泛型,而是使用了局部類型轉換文件:
Conversion02Action.java [java] package org.conversion.action;import java.util.List; import java.util.Map;import org.person.Person;import com.opensymphony.xwork2.ActionSupport;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
[html]Element_lists=org.person.Person Key_maps=java.lang.String Element_maps=org.person.Person
2.jsp
[html]<%@ page language="java" contentType="text/html; charset=utf-8"pageEncoding="utf-8"%><%@taglib prefix="s" uri="/struts-tags" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Insert title here</title> </head> <body> <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> </body> </html>
? Conversion02Action-conversion.properties [html] Element_lists=org.person.Person Key_maps=java.lang.String Element_maps=org.person.Person
三、自定義類型轉換器
1.繼承DefaultTypeConverter
? 如果我們自定義一個類型轉換器,第一種方法是繼承DefaultTypeConverter,并重寫?public Object convertValue(ActionContext context,Object value,Class toType); 這個函數的功能是完成雙向轉換,即從String數組轉到Action屬性及Action屬性轉到String;需要注意的是從String數組轉到Action屬性,而不是String轉到Action屬性;如果只有一個字符串,則取params[0] 即可;
因此一般此函數的模板代碼如下:
[java] public Object convertValue(Map<String, Object> context, Object value,Class toType) {if(toType==String.class){......return String;}else if(toType==Action屬性.class){String params[] = (String[])value;//必須是字符串數組.......return Action屬性;}return null;}
完成自定義類型轉換器編寫后,如果需要使用此轉換器,就需要配置,通常有兩種配置方法: 1.局部類型轉換文件中配置,僅對特定的Action的特定屬性有效,比如在Action1中有aa屬性,則僅對Action1的aa屬性有效; 2.全局類型轉換文件中配置,對某個類型都有效;比如對Person注冊了類型轉換器,則對任何Person和String的轉換都有效;
全局類型轉換文件命名為: xwork-conversion.properties,通常放在WEB-INF\classes下; 文件內容如:attributeName=ConvertClass ,比如aa=org.convert.Converter1 attributeName表示屬性名稱, convertClass表示轉換器的實現類;
局部類型轉換文件命名為:ActionName-conversion.properties,放在特定Action的目錄下; 文件內容如: typeName=ConvertClass,比如 org.person.Person = org.convert.Converter2 注意:typeName表示轉換類型,convertClass表示轉換器的實現類;
代碼示例:
Conversion03Action.java
[java] package org.conversion.action;import org.person.Person;import com.opensymphony.xwork2.ActionSupport;public class Conversion03Action extends ActionSupport {private Person p ;public String execute()throws Exception{System.out.println(p.getGender());System.out.println(p.getSalary());return SUCCESS;}public Person getP() {return p;}public void setP(Person p) {this.p = p;}}
Converter01.java
[java]package org.converter;import java.util.Map;import org.person.Person;import com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter;public class Converter01 extends DefaultTypeConverter {@Overridepublic Object convertValue(Map<String, Object> context, Object value,Class toType) {if(toType==String.class){Person p = (Person)value;return p.getSalary()+","+p.getGender();}else if(toType==Person.class){String params[] = (String[])value;String[]values = params[0].split("\\,");Person p = new Person();p.setGender(values[1]);p.setSalary(Double.parseDouble(values[0]));return p;}return null;}}
3.jsp
[html] <%@ page language="java" contentType="text/html; charset=utf-8"pageEncoding="utf-8"%><%@taglib prefix="s" uri="/struts-tags" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Insert title here</title> </head> <body> <s:fielderror></s:fielderror><s:form action="conversion03" ><s:textfield label="薪水,性別" name="p"></s:textfield><s:submit value="提交"></s:submit></s:form> </body> </html>
 
Conversion03Action-conversion.properties
[html] p=org.convert.Converter01
 
 2.繼承StrutsTypeConverter
 
 
StrutsTypeConverter是DefaultTypeConverter的子類,DefaultTypeConverter的類型轉換器是在一個函數中進行雙向轉換,而繼承StrutsTypeConverter的類型轉換器則是將兩個方向分別用兩個函數實現:
[java] @Overridepublic Object convertFromString(Map context, String[] values, Class toClass) {}@Overridepublic String convertToString(Map context, Object o) {}
將DefaultTypeConverter中的Converter01換成如下代碼就可以完成StrutsTypeConverter的類型轉換器;
[java] package org.converter;import java.util.Map;import org.apache.struts2.util.StrutsTypeConverter; import org.person.Person;public class Converter02 extends StrutsTypeConverter {@Overridepublic Object convertFromString(Map context, String[] value, Class toClass) {String params[] = (String[])value;String[]values = params[0].split("\\,");Person p = new Person();p.setGender(values[1]);p.setSalary(Double.parseDouble(values[0]));return p;}@Overridepublic String convertToString(Map context, Object o) {Person p = (Person)o;return p.getSalary()+","+p.getGender();} }
xwork-conversion.properties
[html] org.person.Person=org.converter.Converter02
四、錯誤處理機制
客戶輸入錯誤信息是很正常的事,因此需要對此種行為進行處理,Struts2提供了很好的錯誤處理機制,是由conversionError攔截器自動完成,我們只需要配置輸出什么錯誤信息即可; 當發生類型轉換錯誤時,conversionError攔截器攔截此錯誤,并封裝成fieldError,將此錯誤信息放入ActionContext中,并返回input邏輯視圖;當然在<action>元素中必須配一個類似于<result name="input">/1.jsp</result>的子元素,以應對類型轉換錯誤; 而為了顯示錯誤信息,則在jsp頁面中使用<s:fielderror/>即可顯示錯誤信息; 注意:類型轉換的Action在struts.xml中配置所在包需要extends="struts-default",因此在此文件中包含conversionError攔截器; 這時我們需要配置顯示的錯誤信息,錯誤信息配置方式有兩種:
? 1.配置默認提示信息
在國際化資源文件中配置形如: xwork.default.invalid.fieldvalue={0},錯誤; {0}代表類型轉換錯誤的屬性名稱;
? 2.配置Action特定屬性錯誤信息 在Action范圍的國際化資源文件中配置形如: invalid.fieldvalue.attributeName= 內容 attributeName是Action中的屬性名稱; 我們在上面的程序中添加類型轉換錯誤的消息: 在Conversion04Action_zh_CN.properties中添加:
[html] view plaincopyprint?
意思是對p屬性配置了特定的錯誤提示信息,當p屬性類型轉換錯誤后就會顯示此信息;
?
?
?=============================使用struts2的錯誤處理機制fielderror
必須讓action繼承ActionSupport,否則無法使用
=======================數組轉換
<td><s:textfield label="user1:" name="users" key="username"/></td>
 ??????? <td><s:textfield label="user2:" name="users" key="username"/></td>
 ??????? 
 ??????? converter.User=converter.UserConverter
 ??????? 
 ??????? public class LoginAction implements Action{
 ?????private User[] user;
 ?????public User[] getUser() {
 ??????return user;
 ?????}
 ????
 ?????public void setUser(User[] user) {
 ??????this.user = user;
 ?????}
 ????...
 ????}
 ????
 ????public class UserConverter extends StrutsTypeConverter{
 ????public Object convertFromString(Map map, String[] as, Class class1) {
 ?????if (as.length>1) {
 ??????User[] users = new User[as.length];
 ??????for (int i = 0; i < as.length; i ++) {
 ???????User user = new User();
 ???????String[] userValues = as[i].split(",");
 ???????user.setName(userValues[0]);
 ???????user.setPass(userValues[1]);
 ???????users[i] = user;
 ??????}
 ??????
 ??????return users;
 ?????} else {
 ??????User user = new User();
 ??????String[] userValues = as[0].split(",");
 ??????user.setName(userValues[0]);
 ??????user.setPass(userValues[1]);
 ??????return user;
 ?????}
 ?????
 ????}
 ???
 ????@Override
 ????public String convertToString(Map map, Object obj) {
 ?????if (obj instanceof User[]) {
 ??????User[] users = (User[])obj;
 ??????String result = "[";
 ??????for (User user:users) {
 ???????result += "<" + user.getName() + "," + user.getPass() + ">";
 ??????}
 ??????return result +="]";
 ?????} else {
 ??????User user = (User)obj;
 ??????return "<" + user.getName() + "," + user.getPass() + ">";
 ?????}
 ?????
 ????}
 ???}
?
總結
以上是生活随笔為你收集整理的Struts2之类型转换的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: struts2.2.1.1 类型转换问题
 - 下一篇: 如何使java中double类型不以科学