![Struts 2.x权威指南](https://wfqqreader-1252317822.image.myqcloud.com/cover/84/773084/b_773084.jpg)
4.4.7 数组属性的类型转换器
对于前面的示例应用中的转换器,我们一直只处理字符串数组的第一个数组元素——假设请求参数是单个值,而不是一个字符串数组。实际上,我们必须考虑请求参数是字符串数组的情形,考虑如图4.11所示的输入页面。
![](https://epubservercos.yuewen.com/1C94E6/3590582303459301/epubprivate/OEBPS/Images/figure_0144_0318.jpg?sign=1739695749-9FV5plwZPh67wHge0r7u23kP4e93kmVn-0-99a247c3fd4fce7125da918a00892295)
图4.11 输入多个同名请求参数的页面
此页面中包含两个用户信息的请求参数,名称都是 users,这两个请求参数必须通过getParameterValues方法来获取参数。此时,users请求参数必须是数组类型,或者List类型(实际上,List和数组是完全相通的)。
下面是处理该请求的Action类代码。
程序清单:codes\04\4.4\ArrayConverter\WEB-INF\src\org\crazyit\struts2\action\LoginAction.java
public class LoginAction implements Action { private User[] users; private Date birth; private String tip; // users属性的setter和getter方法 public void setUsers(User[] users) { this.users = users; } public User[] getUsers() { return this.users; } // 省略其他属性的setter和getter方法 ... // 处理请求的execute方法 public String execute() throws Exception { // 调用users数组的第一个元素的name属性和pass属性进行判断 if (getUsers()[0].getName().equals("crazyit") && getUsers()[0].getPass().equals("leegang") ) { setTip("转换成功"); return SUCCESS; } else { setTip("转换失败"); return ERROR; } } }
上面的Action使用了User数组类型属性来封装user请求参数。下面是本应用的类型转换器代码。
程序清单:codes\04\4.4\ArrayConverter\WEB-INF\src\org\crazyit\struts2\action\UserConverter.java
public class UserConverter extends StrutsTypeConverter { // 处理将字符串类型转换成复合类型的方法 public Object convertFromString(Map context, String[] values, Class toClass) { // 如果请求参数数组的长度大于1 if (values.length > 1) { // 创建一个User数组 User[] result = new User[values.length]; // 遍历请求参数数组 for (int i = 0; i < values.length ; i++ ) { // 将每个数组元素转换成一个User实例 User user = new User(); String[] userValues = values[i] .split(","); user.setName(userValues[0]); user.setPass(userValues[1]); // 将转换的User实例装入数组 result[i] = user; } return result; } // 如果请求参数数组的长度为1 else { // 创建一个User实例 User user = new User(); // 将请求参数转换成一个User实例 String[] userValues = values[0].split(","); user.setName(userValues[0]); user.setPass(userValues[1]); return user; } } // 处理把复合类型转换成字符串类型的方法 public String convertToString(Map context, Object o) { // 如果需要转换的值是单个的User实例 if (o instanceof User) { User user = (User)o; return "<" + user.getName() + "," + user.getPass() + ">"; } // 如果需要转换的值是User数组 else if (o instanceof User[]) { User[] users = (User[])o; String result = "["; for (User user : users ) { result += "<" + user.getName() + "," + user.getPass() + ">"; } return result + "]"; } else { return ""; } } }
上面的类型转换器更加完善,它不仅处理了单一请求参数的情形,即values数组长度为1时;也处理了多个请求参数的情形,即 values 数组长度大于 1 的情形。因此,本应用中的类型转换器完全可以代替前面应用里的类型转换器。
在图4.11所示页面的三个输入框内分别输入crazyit,leegang、abc,xyz和2003-02-12,然后提交请求,将看到如图4.12所示的页面。
![](https://epubservercos.yuewen.com/1C94E6/3590582303459301/epubprivate/OEBPS/Images/figure_0146_0319.jpg?sign=1739695749-3h4YfcvRTG5MnevBgSFoi84I4NuEFMGK-0-302e6a7ee3ead62733a8374b1aafff58)
图4.12 数组属性的类型转换器
对于本示例而言,此处使用局部类型转换器和全局类型转换器的效果是相同的。但底层的转换细节是不同的。
如果使用局部类型转换器,那么类型转换器将会对 users 属性本身起作用,此时名为users的请求参数是一个长度为2的数组。因此,convertFromString方法中的value参数是一个长度为2的数组。局部类型转换器对Action的指定属性起作用。因此,Action每包含一个需要类型转换的属性(不管该属性是单个属性,还是以数组形式存在),类型转换器的convertFromString方法只执行一次。
如果使用全局类型转换器,那么类型转换器将会对所有的User类起作用,上面的users请求参数是一个长度为2的字符串数组,它对应于Action的users属性,将转换成一个长度为2的User数组,因此此处类型转换器的convertFromString方法执行两次。