Struts2中的型別轉換
一、在 struts2中,對常用的資料型別已經自動進行了型別轉換工作。
DefaultTypeConverter裡面已經處理了String向其他基本型別的轉化工作。
/** * Default type conversion. Converts among numeric types and also strings. Contains the basic * type mapping code from OGNL. * * @author Luke Blanshard ([email protected]) * @author Drew Davidson ([email protected]
) */ public abstract class DefaultTypeConverter implements TypeConverter { protected static String MILLISECOND_FORMAT = ".SSS"; private static final String NULL_STRING = "null"; private static final Map<Class, Object> primitiveDefaults; private Container container; static { Map<Class, Object> map = new HashMap<>(); map.put(Boolean.TYPE, Boolean.FALSE); map.put(Byte.TYPE, Byte.valueOf((byte) 0)); map.put(Short.TYPE, Short.valueOf((short) 0)); map.put(Character.TYPE, new Character((char) 0)); map.put(Integer.TYPE, Integer.valueOf(0)); map.put(Long.TYPE, Long.valueOf(0L)); map.put(Float.TYPE, new Float(0.0f)); map.put(Double.TYPE, new Double(0.0)); map.put(BigInteger.class, new BigInteger("0")); map.put(BigDecimal.class, new BigDecimal(0.0)); primitiveDefaults = Collections.unmodifiableMap(map); } @Inject public void setContainer(Container container) { this.container = container; } public Object convertValue(Map<String, Object> context, Object value, Class toType) { return convertValue(value, toType); } public Object convertValue(Map<String, Object> context, Object target, Member member, String propertyName, Object value, Class toType) { return convertValue(context, value, toType); } public TypeConverter getTypeConverter( Map<String, Object> context ) { Object obj = context.get(TypeConverter.TYPE_CONVERTER_CONTEXT_KEY); if (obj instanceof TypeConverter) { return (TypeConverter) obj; // for backwards-compatibility } else if (obj instanceof ognl.TypeConverter) { return new XWorkTypeConverterWrapper((ognl.TypeConverter) obj); } return null; } /** * Returns the value converted numerically to the given class type * * This method also detects when arrays are being converted and converts the * components of one array to the type of the other. * * @param value * an object to be converted to the given type * @param toType * class type to be converted to * @return converted value of the type given, or value if the value cannot * be converted to the given type. */ public Object convertValue(Object value, Class toType) { Object result = null; if (value != null) { /* If array -> array then convert components of array individually */ if (value.getClass().isArray() && toType.isArray()) { Class componentType = toType.getComponentType(); result = Array.newInstance(componentType, Array .getLength(value)); for (int i = 0, icount = Array.getLength(value); i < icount; i++) { Array.set(result, i, convertValue(Array.get(value, i), componentType)); } } else { if ((toType == Integer.class) || (toType == Integer.TYPE)) result = (int) longValue(value); if ((toType == Double.class) || (toType == Double.TYPE)) result = doubleValue(value); if ((toType == Boolean.class) || (toType == Boolean.TYPE)) result = booleanValue(value) ? Boolean.TRUE : Boolean.FALSE; if ((toType == Byte.class) || (toType == Byte.TYPE)) result = (byte) longValue(value); if ((toType == Character.class) || (toType == Character.TYPE)) result = (char) longValue(value); if ((toType == Short.class) || (toType == Short.TYPE)) result = (short) longValue(value); if ((toType == Long.class) || (toType == Long.TYPE)) result = longValue(value); if ((toType == Float.class) || (toType == Float.TYPE)) result = new Float(doubleValue(value)); if (toType == BigInteger.class) result = bigIntValue(value); if (toType == BigDecimal.class) result = bigDecValue(value); if (toType == String.class) result = stringValue(value); if (Enum.class.isAssignableFrom(toType)) result = enumValue(toType, value); } } else { if (toType.isPrimitive()) { result = primitiveDefaults.get(toType); } } return result; } /** * Evaluates the given object as a boolean: if it is a Boolean object, it's * easy; if it's a Number or a Character, returns true for non-zero objects; * and otherwise returns true for non-null objects. * * @param value * an object to interpret as a boolean * @return the boolean value implied by the given object */ public static boolean booleanValue(Object value) { if (value == null) return false; Class c = value.getClass(); if (c == Boolean.class) return (Boolean) value; // if ( c == String.class ) // return ((String)value).length() > 0; if (c == Character.class) return (Character) value != 0; if (value instanceof Number) return ((Number) value).doubleValue() != 0; return true; // non-null } public Enum<?> enumValue(Class toClass, Object o) { Enum<?> result = null; if (o == null) { result = null; } else if (o instanceof String[]) { result = Enum.valueOf(toClass, ((String[]) o)[0]); } else if (o instanceof String) { result = Enum.valueOf(toClass, (String) o); } return result; } /** * Evaluates the given object as a long integer. * * @param value * an object to interpret as a long integer * @return the long integer value implied by the given object * @throws NumberFormatException * if the given object can't be understood as a long integer */ public static long longValue(Object value) throws NumberFormatException { if (value == null) return 0L; Class c = value.getClass(); if (c.getSuperclass() == Number.class) return ((Number) value).longValue(); if (c == Boolean.class) return (Boolean) value ? 1 : 0; if (c == Character.class) return (Character) value; return Long.parseLong(stringValue(value, true)); } /** * Evaluates the given object as a double-precision floating-point number. * * @param value * an object to interpret as a double * @return the double value implied by the given object * @throws NumberFormatException * if the given object can't be understood as a double */ public static double doubleValue(Object value) throws NumberFormatException { if (value == null) return 0.0; Class c = value.getClass(); if (c.getSuperclass() == Number.class) return ((Number) value).doubleValue(); if (c == Boolean.class) return (Boolean) value ? 1 : 0; if (c == Character.class) return (Character) value; String s = stringValue(value, true); return (s.length() == 0) ? 0.0 : Double.parseDouble(s); /* * For 1.1 parseDouble() is not available */ // return Double.valueOf( value.toString() ).doubleValue(); } /** * Evaluates the given object as a BigInteger. * * @param value * an object to interpret as a BigInteger * @return the BigInteger value implied by the given object * @throws NumberFormatException * if the given object can't be understood as a BigInteger */ public static BigInteger bigIntValue(Object value) throws NumberFormatException { if (value == null) return BigInteger.valueOf(0L); Class c = value.getClass(); if (c == BigInteger.class) return (BigInteger) value; if (c == BigDecimal.class) return ((BigDecimal) value).toBigInteger(); if (c.getSuperclass() == Number.class) return BigInteger.valueOf(((Number) value).longValue()); if (c == Boolean.class) return BigInteger.valueOf((Boolean) value ? 1 : 0); if (c == Character.class) return BigInteger.valueOf(((Character) value).charValue()); return new BigInteger(stringValue(value, true)); } /** * Evaluates the given object as a BigDecimal. * * @param value * an object to interpret as a BigDecimal * @return the BigDecimal value implied by the given object * @throws NumberFormatException * if the given object can't be understood as a BigDecimal */ public static BigDecimal bigDecValue(Object value) throws NumberFormatException { if (value == null) return BigDecimal.valueOf(0L); Class c = value.getClass(); if (c == BigDecimal.class) return (BigDecimal) value; if (c == BigInteger.class) return new BigDecimal((BigInteger) value); if (c.getSuperclass() == Number.class) return new BigDecimal(((Number) value).doubleValue()); if (c == Boolean.class) return BigDecimal.valueOf((Boolean) value ? 1 : 0); if (c == Character.class) return BigDecimal.valueOf(((Character) value).charValue()); return new BigDecimal(stringValue(value, true)); } /** * Evaluates the given object as a String and trims it if the trim flag is * true. * * @param value * an object to interpret as a String * @param trim * trims the result if true * @return the String value implied by the given object as returned by the * toString() method, or "null" if the object is null. */ public static String stringValue(Object value, boolean trim) { String result; if (value == null) { result = NULL_STRING; } else { result = value.toString(); if (trim) { result = result.trim(); } } return result; } /** * Evaluates the given object as a String. * * @param value * an object to interpret as a String * @return the String value implied by the given object as returned by the * toString() method, or "null" if the object is null. */ public static String stringValue(Object value) { return stringValue(value, false); } protected Locale getLocale(Map<String, Object> context) { Locale locale = null; if (context != null) { locale = (Locale) context.get(ActionContext.LOCALE); } if (locale == null) { LocaleProviderFactory localeProviderFactory = container.getInstance(LocaleProviderFactory.class); locale = localeProviderFactory.createLocaleProvider().getLocale(); } return locale; } }
但是我們還可以生成更加複雜的物件,比如Collection或者Map的例項。
input.jsp
<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %> <%@taglib prefix="s" uri="/struts-tags"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>直接封裝成Map</title> </head> <body> <h3>直接封裝成Map</h3> <s:form action="login"> <s:textfield name="users['one'].name" label="第one個使用者名稱"/> <s:textfield name="users['one'].pass" label="第one個密碼"/> <s:textfield name="users['two'].name" label="第two個使用者名稱"/> <s:textfield name="users['two'].pass" label="第two個密碼"/> <tr> <td colspan="2"><s:submit value="轉換" theme="simple"/> <s:reset value="重填" theme="simple"/></td> </tr> </s:form> </body> </html>
welcome.jsp
<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
<%@taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>轉換結果</title>
</head>
<body>
<s:actionmessage/>
key為one的使用者名稱為:<s:property value="users['one'].name"/><br/>
key為one的密碼為:<s:property value="users['one'].pass"/><br/>
key為two的使用者名稱為:<s:property value="users['two'].name"/><br/>
key為two的密碼為:<s:property value="users['two'].pass"/><br/>
</body>
</html>
struts.xml
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<!-- 亂碼解決 預設utf-8 是i18n(1 2 3 的1 internationalization中間18個單詞) 不是il8n -->
<constant name="struts.i18n.encoding" value="GBK"></constant>
<package name="lee" extends="struts-default">
<action name="login" class="org.crazyit.app.action.LoginAction">
<result>/WEB-INF/content/welcome.jsp</result>
<result name="error">/WEB-INF/content/welcome.jsp</result>
</action>
<action name="*">
<result>/WEB-INF/content/{1}.jsp</result>
</action>
</package>
</struts>
Action處理類
import com.opensymphony.xwork2.ActionSupport;
import java.util.Map;
import org.crazyit.app.domain.*;
public class LoginAction extends ActionSupport{
// Action類裡包含一個Map型別的成員變數
// Map的value型別為User型別
private Map<String , User> users;
// users的setter和getter方法
public void setUsers(Map<String , User> users){
this.users = users;
}
public Map<String , User> getUsers(){
return this.users;
}
public String execute() throws Exception{
// 在控制檯輸出Struts 2封裝產生的Map物件
System.out.println(getUsers());
// 根據Map集合中key為one的User例項來決定控制邏輯
if (getUsers().get("one").getName().equals("張三")
&& getUsers().get("one").getPass().equals("123456") )
{
addActionMessage("登入成功!");
return SUCCESS;
}
addActionMessage("登入失敗!!");
return ERROR;
}
}
public class User{
private String name;
private String pass;
// name的setter和getter方法
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
// pass的setter和getter方法
public void setPass(String pass){
this.pass = pass;
}
public String getPass(){
return this.pass;
}
@Override
public String toString() {
return "User [name=" + name + ", pass=" + pass + "]";
}
}
上面生成了一個Map物件,程式必須使用泛型,同樣的如果想把Map改成List<User>,只需要把上面的users['one'].name改成users[下標].name 即可。
如果我不用泛型要怎麼辦,這個時候就可以指定集合元素型別。
只需要一個區域性型別轉換檔案即可,下面用List來演示。
區域性型別轉換檔案:
命名:ActionName-conversion.properties ActionName時需要Action的類名,後面的固定。
位置:和Action類檔案相同的位置。
配置檔案寫法:
Element_<ListPropName>=<ElementType> <ListPropName>替換成Listj集合屬性的名稱,<ElementType> 替換成集合元素型別。
LoginAction-conversion.properties
Element_users=org.crazyit.app.domain.User
Map集合需要寫兩個:
1)指定key
Key_<MapPropName>=<keyType> <MapPropName>時Map型別的屬性,<keyType>Map key值的全限定類名。
2)指定value
Element_<MapPropName>=<ValueType> <MapPropName>時Map型別的屬性,<ValueType>Map ValueType值的全限定類名。
比如
Key_users=java.lang.String
Element_users=org.crazyit.app.domain.User
struts.xml
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<!-- 亂碼解決 預設utf-8 是i18n(1 2 3 的1 internationalization中間18個單詞) 不是il8n -->
<constant name="struts.i18n.encoding" value="GBK"></constant>
<package name="lee" extends="struts-default">
<action name="login" class="org.crazyit.app.action.LoginAction">
<result>/WEB-INF/content/welcome.jsp</result>
<result name="error">/WEB-INF/content/welcome.jsp</result>
</action>
<action name="*">
<result>/WEB-INF/content/{1}.jsp</result>
</action>
</package>
</struts>
Action類
import com.opensymphony.xwork2.ActionSupport;
import java.util.List;
import org.crazyit.app.domain.*;
public class LoginAction extends ActionSupport{
// Action類裡包含一個不帶泛型的List型別的成員變數
private List users;
// users的setter和getter方法
public void setUsers(List users){
this.users = users;
}
public List getUsers(){
return this.users;
}
public String execute() throws Exception{
// 在控制檯輸出Struts 2封裝產生的List物件
System.out.println(getUsers());
// 因為沒有使用泛型,所以要進行強制型別轉換
User firstUser = (User)getUsers().get(0);
// users屬性的第一個User例項來決定控制邏輯
if (firstUser.getName().equals("張三")
&& firstUser.getPass().equals("123456") )
{
addActionMessage("登入成功!");
return SUCCESS;
}
addActionMessage("登入失敗!!");
return ERROR;
}
}
public class User{
private String name;
private String pass;
//name屬性的setter和getter方法
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
//pass屬性的setter和getter方法
public void setPass(String pass){
this.pass = pass;
}
public String getPass(){
return this.pass;
}
@Override
public String toString() {
return "User [name=" + name + ", pass=" + pass + "]";
}
}
input.jsp
<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
<%@taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>直接封裝成List</title>
</head>
<body>
<h3>直接封裝成List</h3>
<s:form action="login">
<s:textfield name="users[0].name" label="第一個使用者名稱"/>
<s:textfield name="users[0].pass" label="第一個密碼"/>
<s:textfield name="users[1].name" label="第二個使用者名稱"/>
<s:textfield name="users[1].pass" label="第二個密碼"/>
<tr>
<td colspan="2"><s:submit value="轉換" theme="simple"/>
<s:reset value="重填" theme="simple"/></td>
</tr>
</s:form>
</body>
</html>
welcome.jsp
<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
<%@taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>轉換結果</title>
</head>
<body>
<s:actionmessage/>
第一個User例項的使用者名稱為:<s:property value="users[0].name"/><br/>
第一個User例項的密碼為:<s:property value="users[0].pass"/><br/>
第二個User例項的使用者名稱為:<s:property value="users[1].name"/><br/>
第二個User例項的密碼為:<s:property value="users[1].pass"/><br/>
</body>
</html>
甚至可以處理Set集合,但是需要注意的是Set集合裡的元素必須有一個唯一標識。
Action類
import com.opensymphony.xwork2.*;
import java.util.Date;
import java.util.Set;
public class LoginAction extends ActionSupport{
private Set users;
private Date birth;
// users的setter和getter方法
public void setUsers(Set users){
this.users = users;
}
public Set getUsers(){
return this.users;
}
// birth的setter和getter方法
public void setBirth(Date birth){
this.birth = birth;
}
public Date getBirth(){
return this.birth;
}
// 沒有提供execute()方法,
// 將直接使用ActionSupport的execute()方法
}
型別轉換器
import java.util.*;
import org.apache.struts2.util.StrutsTypeConverter;
import org.crazyit.app.domain.*;
public class UserConverter extends StrutsTypeConverter{
public Object convertFromString(Map context, String[] values, Class toClass){
Set result = new HashSet();
for (int i = 0; i < values.length ; i++ ){
// 建立一個User例項
User user = new User();
// 只處理請求引數陣列第一個陣列元素,
// 並將該字串以英文逗號分割成兩個字串
String[] userValues = values[i].split(",");
// 為User例項的屬性賦值
user.setName(userValues[0]);
user.setPass(userValues[1]);
// 將User例項新增到Set集合中
result.add(user);
}
return result;
}
public String convertToString(Map context, Object o){
// 如果待轉換物件的型別是Set
if (o.getClass() == Set.class){
Set users = (Set)o;
String result = "[";
for (Object obj : users ){
User user = (User)obj;
result += "<" + user.getName()
+ "," + user.getPass() + ">";
}
return result + "]";
}else{
return "";
}
}
}
上面程式碼實現了字串陣列和List結合的轉換處理,還需要讓struts2明白Set集合元素的標識屬性,指定Struts2根據該標識屬性來存取Set集合元素。
User類:
public class User{
private String name;
private String pass;
// name的setter和getter方法
public void setName(String name){
this.name = name;
}
public String getName()
{
return this.name;
}
// pass的setter和getter方法
public void setPass(String pass){
this.pass = pass;
}
public String getPass(){
return this.pass;
}
public boolean equals(Object obj){
// 如果待比較的兩個物件是同一個物件,直接返回true
if(this == obj){
return true;
}
// 只有當obj是User物件
if (obj != null && obj.getClass() == User.class){
User user = (User)obj;
// 兩個物件的name屬性相等即認為二者相等
return this.getName().equals(user.getName());
}
return false;
}
// 根據name計算hashCode
public int hashCode(){
return name.hashCode();
}
}
該User重寫了 equals 和 hashCode,該User類的標識屬性是name,當兩個User的name相同時認為它們相同。
使用區域性型別轉換檔案來指定Set元素的標識屬性
寫法:
KeyProperty_<SetPropName>=<KeyPropName> SetPropName替換成屬性名 KeyPropName替換成元素的標識屬性。
#指定users屬性的型別轉換器是UserConverter
users= org.crazyit.app.converter.UserConverter
# 指定users集合屬性裡集合元素的索引屬性是name
KeyProperty_users=name
在jsp頁面直接通過索引來訪問Set元素
welcome.jsp
<%@ page language="java" contentType="text/html; charset=GBK"%>
<%@taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<title>轉換結果</title>
</head>
<body>
<s:actionmessage/>
<s:property value="users"/>
<!-- 訪問users集合屬性裡索引屬性值為crazyit.org的元素的name屬性-->
使用者crazyit.org的使用者名稱為:<s:property value="users('crazyit.org').name"/><br/>
<!-- 訪問users集合屬性裡索引屬性值為crazyit.org的元素的pass屬性-->
使用者crazyit.org的密碼為:<s:property value="users('crazyit.org').pass"/><br/>
<!-- 訪問users集合屬性裡索引屬性值為fkit的元素的name屬性-->
使用者fkit的使用者名稱為:<s:property value="users('fkit').name"/><br/>
<!-- 訪問users集合屬性裡索引屬性值為fkit的元素的pass屬性-->
使用者fkit的密碼為:<s:property value="users('fkit').pass"/><br/>
生日為:<s:property value="birth"/><br/>
</body>
</html>
訪問Set元素用的是圓括號,而不是方括號。對於陣列,List和Map屬性,則通過方括號來訪問指定集合元素。
input.jsp
<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
<%@taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Set屬性的型別轉換</title>
</head>
<body>
<h3>Set屬性的型別轉換</h3>
<s:form action="login">
<s:textfield name="users" label="第一個使用者資訊"/>
<s:textfield name="users" label="第二個使用者資訊"/>
<s:textfield name="birth" label="使用者生日"/>
<tr>
<td colspan="2"><s:submit value="轉換" theme="simple"/>
<s:reset value="重填" theme="simple"/></td>
</tr>
</s:form>
</body>
</html>
struts.xml
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<constant name="struts.i18n.encoding" value="gbk"></constant>
<!-- 配置國際化資原始檔 -->
<constant name="struts.custom.i18n.resources" value="GBK"/>
<package name="lee" extends="struts-default">
<!-- 定義處理使用者請求的Action -->
<action name="login" class="org.crazyit.app.action.LoginAction">
<!-- 配置名為input的邏輯檢視,當轉換失敗後轉入該邏輯檢視 -->
<result name="input">/WEB-INF/content/input.jsp</result>
<!-- 配置名為success的邏輯檢視 -->
<result>/WEB-INF/content/welcome.jsp</result>
<result name="error">/WEB-INF/content/welcome.jsp</result>
</action>
<action name="*">
<result>/WEB-INF/content/{1}.jsp</result>
</action>
</package>
</struts>
二、但是對於自定義型別struts2沒法去做型別轉換工作。需要自定義型別轉換器來實現型別的轉換。
我想要實現一個點的輸入比如(1,2)
輸入頁面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="add.action" method="post">
座標點::<input type="text" name="point">
<input type="submit" value="提交">
</form>
</body>
</html>
point類
public class Point {
private int x;
private int y;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
@Override
public String toString() {
return "toString方法: toString("+this.x+","+this.y+")";
}
}
Action處理類
import com.opensymphony.xwork2.Action;
import cn.sxt.vo.Point;
public class PointAction {
private Point point;
public Point getPoint() {
return point;
}
public void setPoint(Point point) {
this.point = point;
}
//獲取頁面提交的座標點
public String execute() {
System.out.println("x="+point.getX()+"\ty="+point.getY());
return Action.SUCCESS;
}
}
struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<package name="default" extends="struts-default" namespace="/">
<action name="add" class="cn.sxt.action.PointAction">
<result >/sucess.jsp</result>
</action>
</package>
</struts>
就這樣去輸入提交的話會報錯的(空指標異常),應為struts2無法處理。
自定義型別轉換器就是解決這種問題的。
2、型別轉換的實現步驟
a)新建一個型別轉換器類繼承 StrutsTypeconverter類(實現兩個抽象方法),繼承DefaultTypeConverter也可以(只需要實現一個抽象方法)
import java.util.Map;
import org.apache.struts2.util.StrutsTypeConverter;
import cn.sxt.vo.Point;
/**
* 之定義型別轉換器
* @author yuanyu
*
*/
/*
* 使用型別轉換的步驟:
a) 編寫型別轉換器--繼承 StrutsTypeConverter 類
b) 編寫 xwork-conversion.properties 的配置檔案,放於 src 下;內容為 要轉換的型別=型別轉換器
*/
//DefaultTypeConverter
//static {
// Map<Class, Object> map = new HashMap<>();
// map.put(Boolean.TYPE, Boolean.FALSE);
// map.put(Byte.TYPE, Byte.valueOf((byte) 0));
// map.put(Short.TYPE, Short.valueOf((short) 0));
// map.put(Character.TYPE, new Character((char) 0));
// map.put(Integer.TYPE, Integer.valueOf(0));
// map.put(Long.TYPE, Long.valueOf(0L));
// map.put(Float.TYPE, new Float(0.0f));
// map.put(Double.TYPE, new Double(0.0));
// map.put(BigInteger.class, new BigInteger("0"));
// map.put(BigDecimal.class, new BigDecimal(0.0));
// primitiveDefaults = Collections.unmodifiableMap(map);
//}
//
//public abstract class StrutsTypeConverter extends DefaultTypeConverter {
// public Object convertValue(Map context, Object o, Class toClass) {
// if (toClass.equals(String.class)) {
// return convertToString(context, o);//物件轉換為String
// } else if (o instanceof String[]) {
// return convertFromString(context, (String[]) o, toClass); //string 轉換為物件
// } else if (o instanceof String) {
// return convertFromString(context, new String[]{(String) o}, toClass);
// } else {
// return performFallbackConversion(context, o, toClass);
// }
// }
public class PointConverter extends StrutsTypeConverter /**繼承DefaultTypeConverter(預設型別轉換器),也可以*/ {
/**
* 表達提交的資料在這個方法中被轉換 將String 轉換為指定的型別
* Converts one or more String values to the specified class.
*
* @param context the action context
* @param values the String values to be converted, such as those submitted from an HTML form 從表達上提交的字串
* @param toClass the class to convert to 轉換為這種型別
* @return the converted object
*/
@Override
public Object convertFromString(Map context, String[] values, Class toClass) {
System.out.println("PointConverter.convertFromString()");
String value = values[0];
Point point = new Point();
point.setX(Integer.parseInt(value.substring(1, value.indexOf(","))));//(1,2)
point.setY(Integer.parseInt(value.substring(value.indexOf(",")+1, value.lastIndexOf(")"))));
return point;
}
/**
*將指定的型別轉換為Strig
*使用ognl表示式獲取值時會呼叫該方法 EL表示式獲取的時候不會呼叫
* Converts the specified object to a String.
*
* @param context the action context
* @param o the object to be converted
* @return the converted String
*/
@Override
public String convertToString(Map context, Object o) {
System.out.println("PointConverter.convertToString()");
Point p = (Point)o;
return "("+p.getX()+","+p.getY()+")";
}
}
b)在src下建立xwork-conversion.properties配置檔案(全域性型別轉換器 用什麼型別轉換器去轉換它)。當預設的型別轉換器沒有時它會去找自己定義的型別轉換器。
#be converted type=converter
cn.sxt.vo.Point=cn.sxt.converter.PointConverter
顯示頁面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>(${point.x},${point.y})</h1>
<h1>EL表示式獲取:${point}</h1>
<h1>ognl表示式或:<s:property value="point"/></h1>
</body>
需要重新point的toStrin()方法,不然後面打印出來的是地址。
使用ognl表示式獲取值時才會呼叫convertToString()方法,資料的賦值就是通過ognl表示式和型別轉換器,由於資料被放在了請求域裡面,我可以直接用el表示式去獲取,el表示式是不會用convertToString()方法的,struts2是推薦用ognl表示式獲取值的。