zoukankan      html  css  js  c++  java
  • struts2自定义类型转换器

    首先,何为struts2的类型转换器?

    类型转换器的作用是将请求中的字符串或字符串数组参数与action中的对象进行相互转换。

    一、大部分时候,使用struts2提供的类型转换器以及OGNL类型转换机制即可满足大部分类型转换需求。如:

    类User.java

    package models;
    
    public class User {
        private String username;
        private String password;
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
    }

    类LoginAction

    package actions;
    
    import java.util.List;
    
    import models.User;
    
    import com.opensymphony.xwork2.ActionSupport;
    
    public class LoginAction extends ActionSupport {
    
        private User user;
    
        public User getUser() {
            return user;
        }
    
        public void setUser(User user) {
            this.user = user;
        }
    
        @Override
        public String execute() throws Exception {
            if (getUser().getUsername().equals("yangys")
                    && getUser().getPassword().equals("123")) {
                return SUCCESS;
            }
            return ERROR;
        }
    
    }

    login.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@taglib prefix="s" uri="/struts-tags"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title><s:text name="login page"></s:text></title>
    </head>
    <body>
        <s:form action="login">
            <s:textfield name="user.username" key="username" />
            <s:password name="user.password" key="password" />
            <s:submit value="login" />
        </s:form>
    </body>
    </html>

    不用做任何处理,表单中的user.username和user.password即可映射到LoginAction中的user对象上。

    注:需提供相关的getter与setter

    二、在特殊情况下,这种类型转换满足不了需求,比如需要把一个复杂字符串转换为一个对象。

    如用户输入"huaihaizi,123"需要将huaihaizi映射到username,把123映射到password。则需要提供自定义类型转换器并将其注册到struts2中,供系统调用并完成类型转换。

     为了模拟此需求,将login.jsp改为如下,通过一个user输入框输入用户名密码,以逗号分隔。

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@taglib prefix="s" uri="/struts-tags"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title><s:text name="login page"></s:text></title>
    </head>
    <body>
        <s:form action="login">
            <s:textfield name="user" key="user" />
            <s:submit value="login" />
        </s:form>
    </body>
    </html>

    User.java与LoginAction.java保持不变。此时为了达到user输入框中的内容映射到user对象的username和password上,需要编写一个自定义转换器类。在OGNL项目中有一个TypeConvert接口,这个借口就是自定义类型转换器必须实现的接口,该接口定义如下。

    public interface TypeConverter {
        public Object convertValue(Map context, Object target, Member member,
                String propertyName, Object value, Class toType);
    }

    实现自定义类型转换器必须实现上面的接口,但是该接口过于复杂,所以OGNL提供了实现类DefaultTypeConverter,通常都采用继承并重写DefaultTypeConverter的convertValue()方法来实现自定义类型转换器,如上需求,需要编写UserConverter.java,代码如下:

    package converters;
    
    import java.util.Map;
    
    import models.User;
    import ognl.DefaultTypeConverter;
    
    public class UserConverter extends DefaultTypeConverter {
    
        @Override
        public Object convertValue(Map context, Object value, Class toType) {
            if (toType == User.class) {
                String[] params = (String[]) value;
                User user = new User();
                user.setUsername(params[0].split(",")[0]);
                user.setPassword(params[0].split(",")[1]);
                return user;
            } else if (toType == String.class) {
                User user = (User) value;
                String userString = "<" + user.getUsername() + ","
                        + user.getPassword() + ">";
                return userString;
            }
            return null;
        }
    }

    这里,convertValue方法就是执行类型转换逻辑的,参数value是转换前的值,toType是转换目标类型,通过判断toType来执行转换方向的逻辑代码。如此例中,toType==User.class时,即为将页面字符串转换成User类的对象,由于适应页面控件参数的通用性,页面参数统一包装成了字符串数组,如果是一个字符串,则为长度1的字符串数组。比如此例中,输入为"huaihaizi,123",则把huaihaizi赋值给user对象的username,把123赋值给user对象的password,并将此user返回即可。反之则把user对象的username和password拼接成字符串返回。

    三、struts2提供了一个StrutsTypeConverter抽象类,这个类是DefaultTypeConverter的子类,将convertValue的两个转换方向拆分成了两个方法,

    convertFromString(Map context,String[] values,Class toClass)

    convertToString(Map context ,Object o)

    逻辑更为清楚,用法与DefaultTypeConverter一致。

    三、然后通过在struts2项目中注册此自定义类型转换器即可,注册此自定义类型转换器有三种方式。

    1.注册局部类型转换器,局部类型转换器仅仅对某个Action的属性起作用

    局部类型转换器则是在该Action同一目录下添加ActionName-convertion.properties,并在内部添加一行映射关系<propName>=<ConverterClass>。本例子中在LgoinAction.java所在包下添加LoginAction-convertion.properties文件,并在文件中添加user=converters.UserConverter即可。

    2.注册全局类型转换器,全局类型转换器对所有Action的特定类型的属性都会生效

    在源代码根路径下提供xwork-convertion.properties文件。并在文件中添加<propType>=<ConverterClass>。本例子中在src目录下添加xwork-convertion.properties文件,并在文件中添加models.User=converters.UserConverter即可。

    3.使用JDK1.5的注解来注册类型转换器。

    局部类型转换器与全局类型转换器的区别:局部类型转换器只针对局部变量进行一次性转换,比如该局部变量是个List<User>,也是在局部类型转换器中对该变量进行一次转换。如果用全局类型转换器,则该List中的每一个User都将进行一次转换。

    四、处理Set集合属性的类型转换,一般情况下不建议在Action中使用Set集合属性,因为Set集合里元素是无序的,所以Struts2不能准确的将参数转换成Set集合里的元素,也不能准确的读取Set集合里的元素。除非Set集合的每个元素都有一个唯一标示,比如对于上面的User类来讲,将username做为标识,则在Action的Set<User>中不能存在两个User对象的username相同,需要重写User的equals和hashCode方法。

    @Override
    public int hashCode() {
        // TODO Auto-generated method stub
        return getUsername().hashCode();
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        } else if (obj != null && obj.getClass() == User.class) {
            User objUser = (User) obj;
            if (objUser.getUsername().equals(this.getUsername())) {
                return true;
            }
        }
        return false;
    }

    然后在局部类型转换器注册文件中指定该Set集合元素的标识。如该Set集合为users,则上面讲过在LoginAction-conversion.properties中添加users=converters.UserConverter 即可注册该局部类型转换器,现在此行下面添加KeyProperty_users=username则可以制定users变量的唯一标识属性是username。

  • 相关阅读:
    用上CommonMark.NET,.NET平台终于有了好用的markdown引擎团队
    上周热点回顾(9.21-9.27)团队
    云计算之路-阿里云上:13:43-13:44之间RDS故障影响了全站的正常访问团队
    CentOS6.5下如何正确下载、安装Intellij IDEA、Scala、Scala-intellij-bin插件、Scala IDE for Eclipse助推大数据开发(图文详解)
    spark-2.2.0-bin-hadoop2.6和spark-1.6.1-bin-hadoop2.6发行包自带案例全面详解(java、python、r和scala)之Basic包下的JavaPageRank.java(图文详解)
    spark-2.2.0-bin-hadoop2.6和spark-1.6.1-bin-hadoop2.6发行包自带案例全面详解(java、python、r和scala)之Basic包下的SparkPageRank.scala(图文详解)
    spark-2.2.0-bin-hadoop2.6和spark-1.6.1-bin-hadoop2.6发行包自带案例全面详解(java、python、r和scala)之Basic包下的JavaTC.java(图文详解)
    spark-2.2.0-bin-hadoop2.6和spark-1.6.1-bin-hadoop2.6发行包自带案例全面详解(java、python、r和scala)之Basic包下的SparkTC.scala(图文详解)
    Spark Mllib里数据集如何取前M行(图文详解)
    Spark Mllib里如何将数值特征字段用StandardScaler进行标准化(图文详解)
  • 原文地址:https://www.cnblogs.com/yoran-yang/p/5159862.html
Copyright © 2011-2022 走看看