4.4.8 集合属性的类型转换器

如果把上面应用中的users属性不是使用字符串数组封装,而是使用集合属性来处理,则修改上面应用的Action代码为如下形式。

程序清单:codes\04\4.4\ListConverter\WEB-INF\src\org\crazyit\struts2\action\LoginAction.java

public class LoginAction implements Action
{
    // 封装user请求参数的List属性
    private List<User> users;
    // 封装birth请求参数的属性
    private Date birth;
    // 封装处理结果的tip属性
    private String tip;
    // users属性的setter和getter方法
    public void setUsers(List<User> user)
    {
          this.users = users;
    }
    public List<User> getUsers()
    {
          return (this.users);
    }
    // 下面省略了其他属性的setter和getter方法
    ...
    // 处理请求的execute方法
    public String execute() throws Exception
    {
          // 调用List集合的第一个元素的name属性和pass属性进行判断
          if (getUser().get(0).getName().equals("crazyit")
                && getUser().get(0).getPass().equals("leegang") )
          {
                setTip("转换成功");
                return SUCCESS;
          }
          else
          {
                setTip("转换失败");
                return ERROR;
          }
    }
}

因为Action里的users属性是一个List类型,应该在类型转换器中也提供对应的转换,因此提供如下的类型转换器。

程序清单:codes\04\4.4\ListConverter\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)
          {
                // 创建一个List对象,List对象的元素类型是User
                List<User> result = new ArrayList<User>();;
                // 遍历请求参数数组
                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实例装入List对象
                      result.add(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() + ">";
          }
          // 如果需要转换的值是List对象
          else if (o instanceof List)
          {
                List<User> users = (List<User>)o;
                String result = "[";
                for (User user : users )
                {
                      result += "<" + user.getName()
                          + "," + user.getPass() + ">";
                }
                return result + "]";
          }
          else
          {
                return "";
          }
    }
}

显然,上面的类型转换器也是一个完善的类型转换器,它也可以处理当一个请求参数包含多个值的情形。这个类型转换器将字符串数组转换成List对象,与前面将字符串数组转换成User数组的情形相比,并没有太大的不同——仅仅取决于 Action 类里采用怎样的封装策略。如果Action类里以数组来封装请求参数的多个值,则类型转换器将字符串数组转换成User数组;如果Action 类以List封装请求参数的多个值,则类型转换器将字符串数组转换成List对象。

实际上,List对象和数组几乎可以互换使用。即使Action类里使用List对象来封装请求参数的多个值,类型转换器也可以将字符串数组转换成User数组——因为Struts 2默认支持数组和List之间的转换。