3.6 实现集合类型转换器
通过自定义类型转换器,可以将用户请求参数设置到集合类型的属性中。下面将分别介绍如何定义数组属性的类型转换器以及集合属性的类型转换器。
3.6.1 数组属性的类型转换器
假如现在项目需求改变了,在用户输入页中使用两个name属性同为“name”的文本框。这两个请求参数的名称都为name,在服务器端接收到的参数不再是单一的字符串而是一个字符串数组。可以在Action中定义一个Name类型的数组来存放多个Name类型的值。Action类代码如下。
package net.hncu.action; import java.util.Date; import net.hncu.bean.Name; import com.opensymphony.xwork2.ActionSupport; public class InputAction extends ActionSupport { // name属性类型为自定义的Name类型 private Name[] name; // age属性类型为int private int age; // birth属性类型为Date private Date birth; // name属性的setter和getter方法 public Name[] getName() { return name; } public void setName(Name[] name) { this.name = name; } // age属性的setter和getter方法 public int getAge() { return age; } public void setAge(int age) { this.age = age; } // birth属性的setter和getter方法 public Date getBirth() { return birth; } public void setBirth(Date birth) { this.birth = birth; } // execute方法 public String execute() throws Exception { return SUCCESS; } }
Action中接受的是一个Name类型的数组,而客户端浏览器传送的是一个字符串数组类型参数值,如何才能进行转换呢?首先必须通过创建一个自定义的类型转换器,将字符串数组中的值分别取出设置到Name类型实例中。然后再将多个Name实例添加到Name数组中,这样就完成了字符串类型数组到Name类型数组的转换。新建类型转换器代码如下。
package net.hncu.convert; import java.util.Map; import net.hncu.bean.Name; import org.apache.struts2.util.StrutsTypeConverter; public class NameConvert extends StrutsTypeConverter { public Object convertFromString(Map context, String[] values, Class toClass) { // 创建一个Name数组 Name[] names = new Name[values.length]; for (int i = 0; i < values.length; i++) { // 将每个数组元素转换成Name实例 Name nb = new Name(); String[] nameValues = values[i].split(" "); nb.setFirstName(nameValues[0]); nb.setLastName(nameValues[1]); names[i] = nb; } return names; } public String convertToString(Map context, Object o) { // 通过强制转换把o转换成Name实例。 Name[] names = (Name[]) o; // 实例化一个StringBuilder用来构造字符串 StringBuilder sb = new StringBuilder(); // 取出names数组的的每个name实例,并构造字符串 for (Name name : names) { sb.append("firstName is ").append(name.getFirstName()).append( ", lastName is ").append(name.getLastName()).append("; "); } // 返回StringBuilder的字符串形式 return sb.toString(); } }
下面新建一个显示页,在该页面中通过<s:property>标签来输出指定的属性值,代码如下所示。
<%@ page language="java" import="java.util.*" pageEncoding="gb2312"%> <%@ taglib prefix="s" uri="/struts-tags" %> <! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>output</title> </head> <body> <! -- 输出name属性的值 --> <s:property value="name"/><br> <! -- 输出age属性的值 --> age:<s:property value="age"/><br> <! -- 输出birth属性的值 --> birth:<s:property value="birth"/> </body> </html>
别忘了注册类型转换器。下面先打开用户输入页,和上一个示例一样输入用户信息。单击“input”按钮进行提交,页面跳转到显示页,如图3.30所示。
图3.30 显示用户信息
从页面显示看出,通过该类型转换器完成了字符串数组到自定义类型数组之间的转换。
3.6.2 集合属性的类型转换器
假如现在Action中的name属性不使用Name类型的数组,能想出其他的方法来封装用户信息吗?这时可以使用集合来封装用户的信息。
下面修改Action中的name属性,不再使用Name类型的数组,而是使用集合来储存用户信息,修改Action代码如下。
package net.hncu.action; import java.util.Date; import java.util.List; import net.hncu.bean.Name; import com.opensymphony.xwork2.ActionSupport; public class InputAction extends ActionSupport { // name属性类型为自定义的Name类型 private List<Name> name; // age属性类型为int private int age; // birth属性类型为Date private Date birth; // name属性的setter和getter方法 public List<Name> getName() { return name; } public void setName(List<Name> name) { this.name = name; } // age属性的setter和getter方法 public int getAge() { return age; } public void setAge(int age) { this.age = age; } // birth属性的setter和getter方法 public Date getBirth() { return birth; } public void setBirth(Date birth) { this.birth = birth; } // execute方法 public String execute() throws Exception { return SUCCESS; } }
因为Action中name属性是一个List集合,所以应该创建相应的类型转换器用来提供对应的转换。类型转换器代码如下。
package net.hncu.convert; import java.util.ArrayList; import java.util.List; import java.util.Map; import net.hncu.bean.Name; import org.apache.struts2.util.StrutsTypeConverter; public class NameConvert extends StrutsTypeConverter { public Object convertFromString(Map context, String[] values, Class toClass) { // 创建一个ArrayList集合对象,List对象的元素值为Name List<Name> names = new ArrayList<Name>(); for (int i = 0; i < values.length; i++) { // 将每个数组元素转换成Name实例 Name nb = new Name(); String[] nameValues = values[i].split(" "); nb.setFirstName(nameValues[0]); nb.setLastName(nameValues[1]); names.add(nb); } return names; } public String convertToString(Map context, Object o) { // 通过强制转换把o转换List集合对象 List<Name> names = (List<Name>) o; // 实例化一个StringBuilder用来构造字符串 StringBuilder sb = new StringBuilder(); // 取出List集合对象的每个name实例,并构造字符串 for (Name name : names) { sb.append("firstName is ").append(name.getFirstName()).append( ", lastName is ").append(name.getLastName()) .append("; "); } // 返回StringBuilder的字符串形式 return sb.toString(); } }
从上面的代码可以看出,使用List类型和数组没有多大的区别。