详解Struts2的类型转换(4)

本文介绍如何在Struts2框架中实现自定义类型转换器,并针对Set集合进行处理,包括解决元素重复问题及使用StrutsTypeConverter简化转换过程。

五、基于Struts2的自定义类型转换器

上一篇博客中提到的DefaulTypeConverter的convertValue()方法的转换是双向的,需要指定toType属性,然后分别实现不同转换方向的转换逻辑。为了简化类型转换器的实现,Struts2提供了一个StrutsTypeConverter抽象类,它是DefaulTypeConverter的子类。它在不同的转换方向提供给了不同的转换方法,详情请看代码和代码注释:

public class UserConverter_1 extends StrutsTypeConverter{

	@Override
	// 实现将字符串类型转换成复合类型的方法
	public Object convertFromString(Map arg0, String[] arg1, Class arg2) {
		User user = new User();
		String[] uservalues = arg1[0].split(",");
		// 为User实例赋值
		user.setUsername(uservalues[0]);
		user.setPassword(uservalues[1]);
		return user;
	}

	@Override
	// 实现将复合类型转换成字符串类型的方法
	public String convertToString(Map arg0, Object arg1) {
		User user = (User) arg1;
		return "<"+user.getUsername()+","+user.getPassword()+">";
	}

}

上面的代码与之前的convertValue方法的代码几乎是一样的,只是拆分开来,看起来更直观。

 

六、处理Set集合

通常不建议在Action中使用Set集合,因为大家都知道的事实是Set集合是无序的。这样导致了两个问题,第一个就是Struts2不能准确的将请求参数转换为Set集合的元素,第二个就是Struts2也不能准确读取Set集合的元素。

我们看如下的Action

public class LoginAction extends ActionSupport{
	private Set users;
	private Date birth;
	
	public Set getUsers() {
		return users;
	}

	public void setUsers(Set users) {
		this.users = users;
	}

	public Date getBirth() {
		return birth;
	}

	public void setBirth(Date birth) {
		this.birth = birth;
	}
	
}

上面的LoginAction的users属性是Set类型,为了能将请求参数转换为Set集合对象,下面有一个对应的类型转换器。

public class UserConverter extends StrutsTypeConverter{
	@Override
	public Object convertFromString(Map arg0, String[] arg1, Class arg2) {
		Set result = new HashSet();
		for (int i = 0; i < arg1.length; i++) {
			User user = new User();
			String[] userValues = arg1[i].split(",");
			user.setUsername(userValues[0]);
			user.setPassword(userValues[1]);
			result.add(user);
		}
		return result;
	}

	@Override
	public String convertToString(Map arg0, Object arg1) {
		// 如果待转换的类型是Set
		if(arg1.getClass() == Set.class){
			Set users = (Set) arg1;
			String result = "[";
			for (Object object : users) {
				User user = (User) object;
				result += "<"+user.getUsername()+","+user.getPassword()+">";
			}
			return result;
		}
		return "";
	}

}

 

接下来就不能回避一个严肃的问题,在学习Set集合的时候,发现在往HashSet集合放置元素时,会根据其hashCode来判断两个元素是否一样,如果是一样,则后者覆盖前者。而hashCode默认是比较其地址值。于是,对于两个先后new 出来的“张三”,其地址值不一样,所以HashSet会将两个均加入其中。这就不符合实际了,理论上一个Set集合只能有一个“张三”,所以重写HashCode()方法与其紧密的equals()方法就显得格外重要。下面就是重写了这两个方法的User对象。

public class User{
	private String username;
	private String password;
	
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	
	@Override
	public boolean equals(Object obj) {
		// 如果待比较的对象是同一个对象,直接返回true
		if(this == obj){
			return true;
		}
		// 只有当obj是User对象
		if(obj != null && obj.getClass() == User.class){
			User user = (User) obj;
			// 如果两个对象的username属性是一样的话,就认为两个对象是一样的
			// 也就是把username属性作为User实例的标识
			return this.getUsername().equals(user.getUsername());
		}
		return false;
	}
	
	@Override
	public int hashCode() {
		return username.hashCode();
	}
}

从上面的代码中得之本示例是将username属性作为User对象的标识符。

 

Struts2允许通过局部类型转换文件来指定Set集合属性的标识属性,在局部类型转换文件中增加如下一行即可指定Set集合元素的标识属性

KeyProPerty_<SetPropName>=<keyPropName>,等号左边表示的是集合属性名,右边则表示标识属性。

在LoginAction-conversion.properties增加如下配置信息

#指定users属性的类型转换器
users=edu.ctgu.action.converterOfSet.UserConverter
#指定users集合属性里的元素索引属性是username
KeyProperty_users=username

下面是input界面表单和success界面

<s:form action="converter-of-set/login">
	<s:textfield name="users" label="第一个用户信息"/>
	<s:textfield name="users" label="第二个用户信息"/>
	<s:textfield name="birth" label="用户生日"/>
	<s:submit value="转换"/>
</s:form>

 

username1 is:<s:property value="users('rgx').username"/><br>
password1 is:<s:property value="users('rgx').password"/><br>
username2 is:<s:property value="users('lj').username"/><br>
password2 is:<s:property value="users('lj').password"/><br>
birth is:    <s:property value="birth"/>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值