二、Struts 2的类型转换---1.Struts 2中实现自定义的类型转换

来源:互联网 发布:软件设计师下午试题 编辑:程序博客网 时间:2024/06/07 02:50

Struts 2 的类型转换

1.  传统的类型转换过程。

传统的类型转换过程直接通过servlet取得用户的输入参数,然后翻到Bean中,然后可以直接通过servlet生成输出。大致实现过程如下。

public class Regist extends HttpServlet

{

    public void service(HttpServletRequest request,HttpServletResponse response)throws IOException

{

        request.setCharacterEncoding("GBK");

        String name = request.getParameter("username");

        String pass = request.getParameter("pass");

        String strAge = request.getParameter("age");

        String strBirth = request.getParameter("birth");

 

        int age = Integer.parseInt(strAge);

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-DD");

        Date birth = null;

        try

        {

            birth = sdf.parse(strBirth);

        }

        catch (Exception e)

        {

               e.printStackTrace();

        }

        UserBean user = new UserBean(name , pass , age , birth);

 

        response.setContentType("text/html;charset=GBK");

        PrintWriter out = response.getWriter();

        out.println("<html><head><title>");

        out.println("类型转换页面");

        out.println("</title></head><body>");

        out.println("<h1>类型转换页面</h1>");

        out.println(user.getName() + "<br>");

        out.println(user.getPass() + "<br>");

        out.println(user.getAge() + "<br>");

        out.println(user.getBirth() + "<br>");

        out.println("</body></html>");

}

 

    public void destroy()

    {

        super.destroy();

    }

}

 

       正如上面代码,我们先从HttpServletRequest中取出用户输入的参数,然后做一些简单的类型转换后用这些参数去初始化UserBeanUserBean是一个带默认构造函数的POJO。然后是生成输出。显然这样的过程比较繁琐。而且这些步骤都是很程式化的。接下来,我们看以下Struts 2的类型转换器。

 

2.  Struts 2中基于OGNL的类型转换器

Struts 2的类型转换器实际上是基于OGNL实现的。我们先看一下OGNL中提供的TypeConverter接口。

该接口定义如下:

public interface TypeConverter {

       public Object convertValue(Map context, Object target, Member member, String propertyName, Object toType);

}

该接口还有一个实现类:DefaultTypeConverter,我们可以通过继承该类来实现自己的类型转换器。

要继承DefaultTypeConverter类需要重写convertValue方法。

以下是一个示例:

public class UserConverter extends DefaultTypeConverter

{

    public Object convertValue(Map context, Object value, Class toType)

       {

        if (toType == User.class )

              {

                     String[] params = (String[])value;

                     User user = new User();

                     String[] userValues = params[0].split(",");

                     user.setName(userValues[0]);

                     user.setPass(userValues[1]);

                     return user;

 

        }

              else if (toType == String.class )

              {

                     User user = (User) value;

                     return "<" + user.getName() + "," + user.getPass() + ">";

        }

        return null ;

    }

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


我们看到上面的UserConverter继承自 DefaultTypeConverter并重写了 convertValue方法。在convertValue方法中先判断toType是一个User类还是一个String。如果是User,意思就是说要转换得目标类型是User,反之则转换成String。如此,实现UserString之间的相互转换。

上面的实现逻辑并不复杂。那么如何让系统自动去完成这个转换逻辑呢。答案时通过约定的配置文件,把这个转换类和User类联系起来。

根据作用范围的不同分为局部类型转换器和全局类型转换器两种。

局部类型转换器

局部类型转换器的转换逻辑只作用于单个Action的某些属性类。

这个文件的命名规则如下:

ActionName-conversion.propertiesActionName是需要转换器生成的Action的类名,后面的-conversion.properties为固定部分。

这个文件的配置方式也是key-value对。形式如下:

propertyName=类型转换器类

 

比如说我们有个LoginActionAction类,此类中有一个User类的对象user。我们的输入参数是一个以“,”分割的包含User类各属性的String,需要通过上面的UserConverter把输入参数转换成我们需要的User类对象。

那么我们建立一个名为LoginAction-conversion.properties的文件,此文件内容如下。

user=abc.UserConverter

此文件要和LoginAction.class放在同一目录下,既WEB-INF/classes/abc路径下。

如果LoginAction里还有一个User类的对象customer,那么我们再加一行配置语句:

customer=abc.UserConverter

可见局部类型转换器设置的一个Action中每一个对象对应的转换器,如果一个类有多对象则要没个对象都设置一次。显然很麻烦。如果我们想设置User类和UserConverter直接对应起来那么就可以使用全局类型转换器

全局类型转换器

注册一个全局类型转换器要提供一个名为xwork-conversion.properties文件,该文件的内容为复合类型=对应类型转换器。仍然是上面的例子。

建立一个xwork-conversion.properties文件,放在WEB-INF/classes目录下。配置内容如下。

lee.User=lee.UserConverter

该全局类型转换器将会对所有User类型属性起作用。

 

3.  通过StrutsTypeConverter抽象类实现类型转换器

StrutsTypeConverterDefaultTypeConverter的子类。该类中已经重写了convertValue()方法。

 

public abstract class StrutsTypeConverter extends DefaultTypeConverter {
    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);
}

 

还是那前面的例子来说,我们要实现UserConverter只需要重写convertFromString()convertToString()两个方法就可以了。如下:

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;

    }

 

    @Override

    public String convertToString(Map context, Object o){

              User user = (User)o;

              return "<" + user.getName() + "," + user.getPass() + ">";

    }

}

上面的代码应该很容易理解,所以不多解释了。