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表达式获取值的。

猜你喜欢

转载自blog.csdn.net/qq_40794973/article/details/85225241
今日推荐