Struts2 类型转换

一、什么是类型转换

Struts2是一个MVC框架,它需要负责解析HTTP请求参数,而HTTP请求参数全部为字符串,Java为强类型语言,所以必须根据HTTP请求参数将其中的数据转换为需要的数据类型。这个过程便是类型转换。

二、Struts2的类型转换

Struts2中常用的类型转换可以使用OGNL表达式完成,即使用Struts2内建的类型转换器,部分自定义的数据类型有特殊的转换需求时,也可以通过是实现Struts2给出的接口实现自定义的类型转换器。另外Struts2的类型转换会通过conversionError(在默认拦截器栈中)拦截器对出现的转换错误进行自动拦截处理。

三、Struts2内建的类型转换器

  • boolean和Boolean:字符串true会转换为布尔类型值true
  • char和Character:字符串转字符
  • int和Integer:字符串转整型类型
  • long和Long:字符串转长整型
  • float和Float:字符串转单精度浮点型
  • double和Double:字符串转双精度浮点型
  • Date:字符串转日期类型,需要字符串满足一定的格式
  • 数组:多个input表单提交给同一个Action的属性,就会构成一个数组传入到该属性中
  • 集合:默认情况下,假定集合元素类型为String,并创建一个新的ArrayList封装所以的字符串

以上的类型转换由Struts2自动完成

四、基于OGNL的类型转换

通过ONGL实现字符串与基本类型的自动转换,另外还可以通过OGNL进行简单的复合类型转换。下面这个Action中的user为一个普通的JavaBean,拥有两个属性 userName和passWord。

public class LoginAction extends ActionSupport {
    private User user;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
    ...
}

在表单页使用OGNL提交与获取方式:

<!-- 提交 -->
<s:form action="login">
    <s:textfield  name="user.userName"></s:textfield>
    <s:textfield  name="user.passWord"></s:textfield>
</s:form>
<!-- 获取 -->
<s:property value="user.userName"></s:property>
<s:property value="user.passWord"></s:property>

但是User必须用于无参构造器,以及各个属性的setter方法,当然还应该在LoginAction为user属性设置setter方法。

另外如果通过OGNL进行Map、List集合的类型转换:

<!-- Map mapName['keyName'].paramName -->
<!-- 这里Map的key为Stirng类型,value为User类型 -->
<s:textfield name="users['one'].username" label="用户名"></s:textfield>
<s:textfield name="users['one'].password" label="密码"></s:textfield>
<!-- List listName[index].paramName -->
<!-- 这里List存放的是User类型,index为索引 -->
<s:textfield name="users[0].username" label="1用户名"></s:textfield>
<s:textfield name="users[0].password" label="1密码"></s:textfield>
<s:textfield name="users[1].username" label="2用户名"></s:textfield>
<s:textfield name="users[1].password" label="2密码"></s:textfield>

五、指定集合元素类型

集合使用泛型指定集合元素类型时Struts2通过反射创建对应的对象,当不使用泛型时Struts2便不知道转换为什么类型的对象了,此时可以通过Struts2的局部类型转换文件(ActionName-conversion.propertiers)指定元素类型。

如LoginAction.java 中不指定List类型

public class LoginAction extends ActionSupport {
    private List  users;

    public List getUsers() {
        return users;
    }

    public void setUsers(List users) {
        this.users = users;
    }
    ...
}

可以在LoginAction同一把目录下增加一个名为 ‘LoginAction-conversion.propertiers’ 的properties文件:

#Element_List属性名=类型
Element_users=com.ren.bean.User

如果为Map指定key-value:

#key_属性集合名=类型
#Element_属性集合名=类型
Key_users=String
Element_users=User

六、自定义类型转换器

大部分的类型转换可以通过OGNL机制自动实现 ,但是有时需要将一个特殊的字符串转换为一个数据对象,如将字符串“ren,123”转换为一个userName=“ren”;passWord=“123”;的User对象,这时你可以通过实现 TypeConverter 接口或扩展该接口的实现类 DefaultTypeConverter 来实现自定义类型转化器,另外你可以扩展由Struts2提供的抽象类 StrutsTypeConverter 来实现。下面介绍两种方法的区别。

1、DefaultTypeConverter 类:需要自己根据 一个class类型的参数 toType 来判断要进行 String->User 还是 User->String,所以toType即要转换的目标类型。

public class UserConverter extends DefaultTypeConverter {
    @Override
    public Object convertValue(Map context, Object value, Class toType) {
        // context : 类型转换环境上下文
        // value : 需要转换的参数
        //toType : 转换后的目标类型
        if (toType == User.class) {
            String[] params  = (String[])value;
            User user = new User();
            String[] userValues = params[0].split(",");
            user.setUsername(userValues[0]);
            user.setPassword(userValues[1]);
            return user;
        } else if (toType ==  String.class) {
            User user = (User)value;
            return "<" + user.getUsername() + "," + user.getPassword() + ">";
        }
        return null;
    }
}

2、StrutsTypeConverter 类:该类是DefaultTypeConverter 的子类,但是他给出了两个方法分别代表两个不同的类型转换方向,即 String->User: covertFromString() 与 User->String: convertToString()

public class UserStrutsConverter extends StrutsTypeConverter {
    @Override
    public Object convertFromString(Map map, String[] strings, Class aClass) {
        User user = new User();
        String[] userValues = strings[0].split(",");
        user.setUsername(userValues[0]);
        user.setPassword(userValues[1]);
        return user;
    }

    @Override
    public String convertToString(Map map, Object o) {
        User user = (User)o;
        return "<" + user.getUsername() + "," + user.getPassword() + ">";
    }
}

 

七、注册类型转换器

自定义的类型转换器通过注册起效,注册的方法有三种:

  • 局部类型转换器 :仅对某个Action起作用
  • 全局类型转换器:对所有Action的 某个类型起作用
  • 使用JDK1.5的注解注册

1、局部类型转换器:在与Action相同目录下的 AvtionName-conversion.properties (ActionName为Action名)文件中指定,仅对本Action中的某个属性起作用,仅执行一次。

#User 的自定义转换器
#属性名=住转换器
user=com.ren.converter.UserConverter

2、全局类型转换器:在 WEB-INF/classes (idea放在src文件夹下编译项目时会自动放到classes目录下) 文件夹中的 xwork-conversion.properties (固定名字) 文件中指定,对整个web项目中的某个类型起作用,有多少个执行多少次。如:List<User>  长度为n,便执行n次。

#全局转换器配置
#类型名=转换器
com.ren.bean.User=com.ren.converter.UserConverter

一定注意具备类型转换器只针对某个Action中的某个属性起作用,哪怕是一个集合也只会执行一次转换,全局类型转换器则会执行多次,只要需要转换时。 

八 、类型转换中的错误处理

上面的自定义类型转换器 UserConverter 可以将一个像 “ren,123” 的字符串转换为一个 User 实例,用户如果输入已 ‘,’隔开的字符串时它可以成功的完成转换任务,但是当用户输入不带 ‘,’  的字符串时它便 不能起作用了,执行便会出错,或者应该输入数字时用户却输入了字符这同样会出错。值得开心的是Struts2有能力自动的对类型转换中出现的错误进行收集、封装、处理,你不需要在程序中进行任何有关转换错误的处理。

Struts通过 默认拦截器栈中的 conversionError  拦截器进行将出现的错误信息封装成“表单域错误”(FieldError),并将它放入ActionContext 中。但是前提是你的 Action 必须继承 ActionSupport,它将异常信息封装抛出(throws)由拦截器进行处理。(你可以在Struts2默认配置文件 struts-default.xml 中查看默认拦截器栈的定义)

import com.opensymphony.xwork2.ActionSupport;

public class LoginSetAction extends ActionSupport {
    ...
}

另外出现错误后返回 “input” 所以你需要在action中配置一个 name 属性为 input 的 result。

<action name="login" class="com.ren.action.LoginAction">
            <result name="success">/WEB-INF/content/login_success.jsp</result>
            <!--转换失败后返回input-->
            <result name="input">/WEB-INF/content/input.jsp</result>
            <result name="error">/WEB-INF/content/error.jsp</result>
</action>

你可以在 input 视图中使用 <s:fielderror> 标签来显示错误信息。它会输出类似 “Invalid field value for field xxx” 的错误信息,xxx为 Action 名字。如果希望打印中文提示信息,在国际化文件中增加如下语句:

#{0}  为出错Action名
xwork.default.invalid.fieldvalue={0}你的提示信息

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值