4.4.6 基于Struts2的类型转换器

上面的类型转换器都是基于OGNL的DefaultTypeConverter类实现的,基于该类实现类型转换器时,将字符串转换成复合类型要通过convertValue方法实现,将复合类型转换成字符串也是通过 convertValue 方法实现的。因此,我们必须先通过 toType 参数来判断转换的方向,然后分别实现不同转换方向的转换逻辑。

为了简化类型转换器的实现,Struts 2提供了一个StrutsTypeConverter抽象类,这个抽象类是DefaultTypeConverter类的子类。下面是StrutsTypeConverter类的代码。

public abstract class StrutsTypeConverter extends DefaultTypeConverter
{
    // 重写DefaultTypeConverter类的convertValue方法
    public Object convertValue(Map context, Object o, Class toClass)
    {
          // 如果需要把复合类型转换成字符串类型
          if (toClass.equals(String.class))
          {
                return convertToString(context, o);
          }
          // 如果需要把字符串转换成复合类型
          else if (o instanceof String[])
          {
                return convertFromString(context, (String[]) o, toClass);
          }
          // 如果需要把字符串转换成复合类型
          else if (o instanceof String)
          {
                return convertFromString(context, new String[]{(String) o}
                      , toClass);
          }
          else
          {
                return performFallbackConversion(context, o, toClass);
          }
    }
    protected Object performFallbackConversion(Map context, Object o
          , Class toClass)
    {
          return super.convertValue(context, o, toClass);
    }
    public abstract Object convertFromString(Map context, String[] values
          , Class toClass);
    public abstract String convertToString(Map context, Object o);
}

从StrutsTypeConverter的代码可以看出,该类简化了类型转换器的实现,该类已经实现了DefaultTypeConverter 的 convertValue 方法。实现该方法时,它将两个不同转换方向替换成不同方法——当需要把字符串转换成复合类型时,调用 convertFromString 抽象方法;当需要把复合类型转换成字符串时,调用convertToString抽象方法。图4.10显示了转换方向和方法之间的对应关系。

图4.10 转换方向和方法之间的对应关系

理解了转换方向和方法之间的对应关系之后,可以更简单地实现自己的类型转换器——让自己的类型转换器继承StrutsTypeConverter类,并重写convertFromString方法和convertToString方法即可。

下面是基于StrutsTypeConverter实现的类型转换器代码。

// 基于StrutsTypeConverter的类型转换器
public class UserConverter extends StrutsTypeConverter
{
    // 实现将字符串类型转换成复合类型的方法
    public Object convertFromString(Map context, String[] values,
          Class toClass)
    {
          User user = new User();
          String[] userValues = values[0].split(",");
          user.setName(userValues[0]);
          user.setPass(userValues[1]);
          return user;
    }
    // 实现将复合类型转换成字符串类型的方法
    public String convertToString(Map context, Object o)
    {
          User user = (User)o;
          return "<" + user.getName() + "," + user.getPass() + ">";
    }
}

通过继承 StrutsTypeConverter 类来实现类型转换器,分别实现 convertFromString 和convertToString方法,这两个方法分别代表不同的转换逻辑——程序逻辑更加清晰。

上面实现类中的convertFromString方法参数与DefaultTypeConverter类中的convertValue方法参数意义大致相同,此处不再赘述。