类型转换的作用:
实现了表示层与逻辑层数据类型之间的转换。(JSP页面只有String类型,Action层有各种类型),这种数据转换可以放在Action处理类中实现,因为几乎每个Action都涉及到数据转换所以抽出来做了自动(基本类型、OGNL表达式)的类型转换拦截器。
1.处理请求参数
将JSP页面(也可能是其他视图类型)提交的数据(字符串类型),转换成Action中设定的复杂类型属性。
JSP页面中有一个提交属性叫“name”,提交表单后经过类型转换拦截器。拦截器将根据"name"属性名查找目标Action中name属性。根据name属性的类型调用不同的类型转换方法,利用name属性值创建name对象。再通过setName()方法为Action中name属性赋值。
2.处理响应参数
将Action中设定的复杂类型属性,转换成JSP页面(也可能是其他视图类型)中的字符串类型。
Action中有一个"name"属性,根据name类型调用不同的类型转换方法,将name复杂类型转换成字符串(类似于调用了toString()方法)。将转换后的name(字符串类型)保存到ActionContext上下文中。在JSP页面中时候则从ActionContext中获取。
一般情况:表示层一个属性对应逻辑层一个字段。如果字段是基本类型则可以自动转换。
例如:表示层属性loginUser,对应逻辑层loginUser属性。
表示层一个属性对应逻辑层一个复杂对象的一个属性。可以将属性指向复杂对象的一个属性则可以自动转换。
例如:表示层属性user.username,对应逻辑层user对象的username属性。
要求复杂对象必须包含空构造方法,要求复杂对象的属性必须包含get、set方法。
特殊情况:表示层一个属性对应逻辑层一个复杂对象,则需要使用到自定义类型转换。
例如:表示层属性user要求输入格式“username,password”信息,逻辑层由一个user属性对应。
这时需要一个自定义类型转换器对两端的数据进行搭桥(互相转换)。
例如:表示层属性maps的值是一个Map.toString()的结果。逻辑层由一个Map属性对应。
这时需要一个自定义类型转换器对两端的数据进行搭桥(互相转换)。
如何自定义类型转换器
方法一比较复杂
实现TypeConverter接口,实现convertValue(Map context,Object target,Member member,String propertyName,Object value,Class toType);方法。
方法二
继承DefaultTypeConverter类,实现convertValue(Map context,Object value,Class toType)方法。
详解:
1.conventValue方法作用很简单,该方法负责完成类型的转换,不过这种转换是双向的;当需要把字符串转换成User对象时,当需要把User对象转换成字符串时,均通过该方法实现。
通过判断toType的类型即可判断转换的方向。可能是Struts或者User。
2.convertValue方法参数和返回值的意义。
第一个参数:context是类型转换环境的上下文。
第二个参数:value是需要转换的参数。User-->String时value表示User实例。String-->User时value表示请求参数字符串数组。
第三个参数:toType是转换后的目标类型。
返回值:当User-->String时返回值类型是String,String-->User时返回值类型是User。
3.为何当String-->User时value表示一个数组而不是一个字符串。因为在表单提交时多个相同的名称表示一组数据(多个值)需要用数组或集合接受。所以为满足这种情况value的类型是数组。
方法三
继承StrutsTypeConverter类,实现以下两个方法:
//实现将字符串类型转换成复杂类型的方法
public Object convertFromString(Map context,String[] values,Class toClass);
//实现将复杂类型转换成字符串类型的方法
public String convertToString(Map context,Object o);
自定义类型转换与集合的关系
对于MAP、LIST、SET有各自的配置文件要编写,但个人感觉只需要使用OGNL表达式即可输出想要的结果。待测试。
类型转换与异常处理
在类型转换过程中可能发生错误并抛出异常后,conversionError拦截器将拦截异常(之前提到过),将转换错误封装成fieldError,并将其放在ActionContext中。最后跳转到input指定的物理映射页面(需要提前在struts.xml中配置)。
在JSP页面中需要使用<s:fielderror/>标签输出该类型转换错误信息。
效果:在input指定的页面中出现 Invalid field value for field 属性名 的提示信息。很不友好。
修改错误提示信息
Invalid field value for field 属性名 :包含两部分“Invalid field value for field”固定值和 "属性名"动态值。
修改固定值:
通过在国际化配置文件中添加:xwork.default.invalid.fieldvalue={0}字段类型转换失败!
修改动态值:在页面中显示属性名还是很不友好。
创建配置文件
ActionName.properties:ActionName表示需要处理的Action类名。
编写配置文件
#为某个Action特定属性指定特定的校验失败提示信息
invalid.fieldvalue.属性名=提示信息
存放配置文件
与需要处理的Action同一目录
PS:当出错的是一个数组内元素时,提示信息只能做到提示数组有问题。无法指出是那条信息错误了。
如何部署设置自定义类型转换器
设置局部类型转换器:局部类型转换器仅仅对某个Action的属性起作用。
设置全局类型转换器:全局类型转换器对所有Action的特定类型的属性都会生效。
使用JDK1.5D的注释来注册类型转换器(略)。
局部配置:
创建配置文件
ActionName-conversion.properties:ActionName是需要转换器生效的Action类名。其他部分是固定值。
编写配置文件
#指定Action类中user属性需要使用lee.UserConverter类来完成类型转换。
user=lee.UserConverter
存放配置文件
配置文件与Action类放在同一个目录下。
全局配置:
创建配置文件
xwork-conversion.properties文件
编写配置文件
#指定lee.User类的类型转换由lee.UserConverter类处理。
lee.User=lee.UserConverter
存放配置文件
与struts.xml文件同目录下。