问题:当在页面中有一个输入框要求输入的是日期类型的值,有的用户会输入2014-06-04,这样后台Action可以正常接收,但是如果有的用户输入了20140604这样的值,那么后台就不能正常接收该日期值而报错。为了解决这个问题,Struts2引入了自定义类型转换器的概念。
Struts2自定义类型转换器分为局部类型转换器和全局类型转换器。
局部类型转换器(以日期转换为例):
1:首先要写个转换类并且继承DefaultTypeConverter
2:重写convertValue()方法,在该方法中进行数据转换(注:1、2两步不论是局部类型转换器还是全局类型器转换器都要进行)
3:对于局部类型转换器在action类对应的包下放置ActionClassName-conversion.properties文件,ActionClassName是Action的类名,后面的-conversion.properties为固定写法,千万不要拼写错误。如:HelloWorldAction-conversion.properties
4:属性文件中的内容为:要转换的属性名称=类型转换器的全类名(包名+类名)如:date = com.lixue.converter.DateTypeConverter
项目结构:
全局类型转换器(以日期转换为例):
1:如果业务要求项目中所有的日期都要进行转换,那么可以使用全局类型转换器。
2:在src目录下定义一个属性文件命名为:xwork-conversion.properties(文件名称千万不能拼错)。
3:属性文件的内容为:待转换的类型=类型转换器的全类名(包名+类名)如:java.util.Date = com.lixue.converter.DateTypeConverter
项目结构:
前台代码:
<body>
<div>
<form action="helloAction_helloTest.action" method="post">
请输入您的生日: <input name="birthday" type="text" />
<input type="submit" value="提交" />
</form>
</div>
</body>
HelloWorldAction.java代码:
public class HelloWorldAction {
private Date birthday;
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
/* 前台请求的方法 */
public String helloTest() {
/* 设置date的值 */
return "ok";
}
}
自定义类型转换器DateTypeConverter.java代码:
/**
* 自定义日期类型转换器
*/
public class DateTypeConverter extends DefaultTypeConverter {
@SuppressWarnings("rawtypes")
@Override
public Object convertValue(Map<String, Object> context, Object value, Class toType) {
/* 定义需要被转换的时间类型 */
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
System.out.println(toType+"<==>"+Date.class);
try {
/* 如果目标类型为Date类型即从前台将一特定形式的字符串传到后台转换为指定的日期类型 */
if (toType == Date.class) {
/**
*1.参数value表示从前台传过来要转换的值,实际调用的是action中的setter方法。
*2.类似于request.getParameterValues(XXX);所以是数组类型
*3.注:千万不要以为这个数组中装了前台表单中的所有值,不是这样的,这个数组中装的只是要转换的值。
*4.当为复选框的时候就是数组了嘛,这样做是充分考虑了特殊情况滴。
*/
String[] params = (String[]) value;
/**
* 取出字符串数组中对应下标的要转换的值, 这里一般是第一个即下标为0,
* 因为确实没有这样的业务(将要转换的值放在复选框中) 如果有这样的需求取出对应下标的值即可。
*/
return sdf.parse(params[0]);
} else if (toType == String.class) {
/**
*如果要转换的类型为字符串类型器即从Action后台传值到页面,调用getter方法
*那么此时的value对应的就成为了Date类型
*/
Date date = (Date) value;
/* 把date类型转换为字符串 */
return sdf.format(date);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
HelloWorlAction-conversion.properties(局部类型转换器的属性文件,放在对应的Action包下):
birthday=com.lixue.converter.DateTypeConverter
xwork-conversion.properties(全局类型转换器的属性文件,放在src目录下):
java.util.Date=com.lixue.converter.DateTypeConverter
结果页面:
<body>
生日:${birthday} </br>
</body>
自定义枚举类型转换器:
gender.jsp:
<form action="enumAction_test.action" method="post">
请选择性别:<input type="radio" name="gender" value="MAN" checked>男
<input type="radio" name="gender" value="WOMEN">女</br>
<input type="submit" value="提交">
</form>
EnumAction.java:
public class EnumAction {
/*定义性别,默认是男*/
private Gender gender = Gender.MAN;
public Gender getGender() {
return gender;
}
public void setGender(Gender gender) {
this.gender = gender;
}
/*测试方法*/
public String test(){
return "success";
}
}
public enum Gender {
MAN {
@Override
public String getGender() {
return "男";
}
},
WOMEN {
@Override
public String getGender() {
return "女";
}
};
public abstract String getGender();
}
自定义类型转换器EnumTypeConverter.java:
public class EnumTypeConverter extends DefaultTypeConverter {
@SuppressWarnings("rawtypes")
@Override
public Object convertValue(Map<String, Object> context, Object value, Class toType) {
/*从前台到后台即从字符串转为枚举类型*/
if (toType == Gender.class){
/*把value强转为数组类型*/
String[] params = (String[]) value;
return Gender.valueOf(params[0]);
} else if (toType == String.class){
/*从后台action传到前台,即Gender类型转换为String类型 */
/*把value强转为Gender*/
Gender gender = (Gender) value;
return gender.toString();
}
return null;
}
}
全局类型转换器xwork-conversion.properties:
com.lixue.bean.Gender=com.lixue.converter.EnumTypeConverter
结果页面success.jsp:
性别:
<input type="radio" name="gender" value="MAN" ${gender eq "MAN" ? "checked" : ""}/>男
<input type="radio" name="gender" value="WOMEN" ${gender eq "WOMEN" ? "checked" : ""}/>女
</br>