详解Struts2的类型转换(4)

来源:互联网 发布:广州市人工智能行业 编辑:程序博客网 时间:2024/05/22 13:13

五、基于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{@Overridepublic 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;}@Overridepublic String convertToString(Map arg0, Object arg1) {// 如果待转换的类型是Setif(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;}@Overridepublic boolean equals(Object obj) {// 如果待比较的对象是同一个对象,直接返回trueif(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;}@Overridepublic int hashCode() {return username.hashCode();}}
从上面的代码中得之本示例是将username属性作为User对象的标识符。

Struts2允许通过局部类型转换文件来指定Set集合属性的标识属性,在局部类型转换文件中增加如下一行即可指定Set集合元素的标识属性
KeyProPerty_<SetPropName>=<keyPropName>,等号左边表示的是集合属性名,右边则表示标识属性。
在LoginAction-conversion.properties增加如下配置信息
#指定users属性的类型转换器users=edu.ctgu.action.converterOfSet.UserConverter#指定users集合属性里的元素索引属性是usernameKeyProperty_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"/>
0 0
原创粉丝点击