表现层数据处理:
1|----- 类型转换可以
|--基于OGNL表达式
|--可以开发自己的类型转换器
Struts2的conventionError拦截器会自动处理类型转化器的异常
2|----- 数据校验分为
|--客户端校验
|--服务器端校验
1、内建的(字符串类型和以下类型的转换):
boolean Boolean
char Character
int Integer
long Long
float Float
double Double
Date 日期格式使用用户所在Locale的SHORT形式
数组 默认数组元素是字符串,如果用户提供了自定义类型转换器,也可以是其他复合类型的数组
集合 默认假定集合元素类型为String,并创建一个新的ArrayList封装所有的字符串
2、基于OGNL的类型转换
1) 对象
User成员变量
<s:textfield name="user.name" label="用户名">
(使用这种方式时要注意:因为要使用反射创建User类实例,必须为该复合类提供无参构造器
通过user.name为属性赋值所以要求类里有setter方法,
Action里面要有getUser()方法)
2)Map
Map<String,User> users
设置<s:textfield name="users['one'].name" label="第one个用户名"/>
访问<s:property value="users['one'].name"/>
3)Map
List<User> users
设置<s:textfield name="users[0].name" label="第一个用户名"/>
访问<s:property value="users[0].name"/>
3、指定集合元素类型
1)没有使用泛型指定类型的List 集合
通过指定局部类型转换文件来处理
List users
ActionName-convention.properties(放在和Action类文件相同的位置)
文件里指定:List集合属性的名称
List集合里元素的类型
Element_<ListPropName>=<ElementType>
eg. Element_users=com.wj.app.domain.User
2)没有使用泛型指定类型的Map集合
Map users
ActionName-convention.properties
文件里指定(key和value类型):
Key_<MapProName>=<KeyType>
Element_<MapPropName>=ValueType>
4、自定义类型转换器
1) 实现OGNL里的TypeConverter接口,DefaultTypeConverter实现了该接口,所以可以继承该类,并重写convertValue()方法
1 public class UserConverter extends DefaultTypeConverter 2 { 3 // 类型转换器必须重写convertValue方法,该方法需要完成双向转换 4 public Object convertValue(Map context 5 , Object value, Class toType) 6 { 7 // 当需要将字符串向User类型转换时 8 if (toType == User.class ) 9 { 10 // 系统的请求参数是一个字符串数组 11 String[] params = (String[])value; 12 // 创建一个User实例 13 User user = new User(); 14 // 只处理请求参数数组第一个数组元素, 15 // 并将该字符串以英文逗号分割成两个字符串 16 String[] userValues = params[0].split(","); 17 // 为User实例赋值 18 user.setName(userValues[0]); 19 user.setPass(userValues[1]); 20 // 返回转换来的User实例 21 return user; 22 } 23 else if (toType == String.class ) 24 { 25 // 将需要转换的值强制类型转换为User实例 26 User user = (User) value; 27 return "<" + user.getName() + "," 28 + user.getPass() + ">"; 29 } 30 return null ; 31 } 32 }
或者继承StrutsTypeConverter
1 public class UserConverter extends StrutsTypeConverter 2 { 3 // 实现将字符串类型转换成复合类型的方法 4 public Object convertFromString(Map context 5 , String[] values , Class toClass) 6 { 7 // 创建一个User实例 8 User user = new User(); 9 // 只处理请求参数数组第一个数组元素, 10 // 并将该字符串以英文逗号分割成两个字符串 11 String[] userValues = values[0].split(","); 12 // 为User实例赋值 13 user.setName(userValues[0]); 14 user.setPass(userValues[1]); 15 // 返回转换来的User实例 16 return user; 17 } 18 // 实现将复合类型转换成字符串类型的方法 19 public String convertToString(Map context, Object o) 20 { 21 // 将需要转换的值强制类型转换为User实例 22 User user = (User) o; 23 return "<" + user.getName() + "," 24 + user.getPass() + ">"; 25 } 26 }
2)注册类型转换器
三种方式:
局部(对某个Action生效)
在局部类型转换文件下加:<propName>=<ConverterClass>
eg. user=com.wj.app.conventer.UserConverter
全局(对所有Action的特定类型属性都会生效)
WEB-INF/classes下提供xwork-convention.properties文件
加上<propType>=<ConverterClass>
jdk注解
局部和全局区别:局部类型转换器对指定属性进行转换,一个属性只调用一次convertValue()方法。
全局类型转换器对所有Action的特定类型起作用,因此可能对一个属性调用多次 convertValue()方法(当该属性是一个数组或者集合时,里面每个元素都要调用一
次这个方法)。
5、处理Set集合
不建议在Action里使用Set集合属性,因为它无序,所以struts2不能准确转换和获取
除非在Set集合里元素有一个标识属性
Set users
ActionName-convention.properties
文件里指定:
KeyProperty_<SetPropName>=<KeyPropName>
eg. KeyProperty__users=name
访问:<SetPropName>('<indexPropValue>')
(数组,list,map用的是方括号,这里是圆括号)
6、类型转换中的错误处理
1)类型转换错误
Struts2里struts-default.xml默认拦截器栈里定义了conventionError拦截器引用,该拦截器负责将对应错误封装成表单域错误,并将这些错误信息放入ActionContext中,conventionError对转换异常处理后,会跳转到名为input的逻辑视图。
为让Struts2类型转换的错误机制和输入校验生效,必须让Action继承ActionSupport类,因为该类负责收集类型转换错误,输入校验错误,并将它们封装成FieldError对象,添加到ActionContext中。
页面中使用<s:fielderror/>标签可输出类型转换错误信息。
输出中文错误提示信息:在国际化资源文件中加xwork.default.invalid.fieldvalue={0}字段类型转换失败!
对特定字段指定特别指示信息:在Action的局部资源文件中加invalid.fieldvalue.<propName>=<tipMsg>
eg. invalid.field.user.birth=生日信息必须满足yyyy-mm-dd 格式
2)集合属性转换错误
直接传入集合(users)会得到一个转换失败信息,分别传入集合元素(user[0]),会得到每个元素对应转换失败信息。