Struts2颠覆了Web编程的传统,Action中完全去掉了request,response等Servlet API,并自动完成数据转换、赋值。这对Web编程是个革命性的变革。不过,如果需要,仍然可以获取、扩展这些Servlet API,并定制数据转换规则等。
页面上传输的都是字符串,但是后台数据类型是多种多样的,struts2 自动通过request.getParameter(name)获取String类型数据,并通过拦截器将String转换成各种常用的数据类型。
有时候为了满足各种特定的需要,需要自定义数据类型转换器。
自定义数据类型转换器有几个步骤,一一实现。
1、自定义类型转换器
实现自定义类型转换器我们一般有两种方式:
1.1、第一种方式TypeConvert
实现OGNL提供的TypeConvert接口以及实现了TypeConvert接口的DefaultTypeConvert类来实现自定义的类型转换器。
convertValue方法的作用:
该方法负责完成类型的双向转换,为了实现双向转换,我们通过判断toType的类型即可判断转换的方向。toType类型是需要转换的目标类型,如:当toType类型是User类型时,表明需要将字符串转换成User实例;当toType类型是String类型时,表明需要把User实例转换成字符串类型。通过toType类型判断了类型转换的方向后,我们就可以分别实现两个方向的转换逻辑了。实现类型转换器的关键就是实现conertValue方法,该方法有三个参数:
-
第一个参数 context:类型转换的上下文
-
第二个参数 value:需要转换的参数
-
第三个参数 toType:转换后的目的类型
1.2 、基于Struts2的类型转换器
Struts 2提供了一个StrutsTypeConverter的抽象类,这个抽象类是DefaultTypeConverter类的子类。开发时可以直接继承这个类来进行转换器的构建。通过继承该类来构建类型转换器,可以不用对转换的类型进行判断(和第一种方式的区别),下面我们来看一下StrutsTypeConverter类的
该类已经实现了DefaultTypeConverter的convertValue方法。实现该方法时,它将两个不同转换方向替换成不同方法——当需要把字符串转换成复合类型时,调用convertFromString抽象方法;当需要把复合类型转换成字符串时,调用convertToString抽象方法,
2、注册自定义类型转换器:
实现了自定义的类型转换器之后,将该类型转换器注册在Web应用中,Struts2框架才可以正常使用该类型转换器,类型转换器的注册分为两种,
2.1、注册局部类型转换器。
局部类型转换器仅仅对某个Action起作用。局部类型转换器非常简单,只需要在相应的Action目录下新建一个资源文件。该资源文件名格式如下。ActionName-conversion.properties。其中ActionName表示需要进行转换的Action的类名,“-conversion.properties”字符串则是固定格式的。该文件也是一个典型Properties文件,文件由键值对组成:propertyName = 类型转换器类
如:name=util.NameConvert
name:表示要进行转换的属性
util.NameConvert:表示要进行转换的自定义类型转换器。
注意:该属性文件应该与ActionName.class放在相同位置。
2.2、注册全局类型转换器。
对所有Action的特定类型的属性都会生效。
全局类型转换器,必须提供一个xwork-conversion.properties文件。文件必须保存在classes目录下。该资源文件名格式如下:
复合类型=对应的类型转换器
复合类型:指定需要完成类型转换的复合类
对应的类型转换器:指定所指定类型转换的转换器。
如:注册User类的全局类型转换器为:UserConverter
cn.wjz.bean.User = cn.wjz.util.UserConverter
注意:如果局部类型转换和全局类型转换同时存在的话,局部类型转换具有较高的优先级,也就是以局部类型转换器为主。
2.3、集合类型的类型转换
对于List元素来说,内容如: Element_attributeName=typeName;
对于Map元素来说,
(1)如果表示key的类型,则:Key_attributeName=typeName;
(2)如果表示value的类型,则为:Element_attributeName=typeName;
3、 实例:日期转换器
3.1 、创建一个转换器
简写,其它类型不写了
package convertor;
import ognl.DefaultTypeConverter;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Map;
/**
* @author JDIT
*/
public class DateTimeConvertor extends DefaultTypeConverter {
private DateFormat[] dateFormats = {
new SimpleDateFormat("yyyy-MM-dd"), new SimpleDateFormat("yyyy/MM/dd"), new SimpleDateFormat("yy-MM-dd")
};
private DateFormat[] timeFormat = {
new SimpleDateFormat("HH:mm:ssss"), new SimpleDateFormat("HH:mm")
};
@Override
public Object convertValue(Map context, Object value, Class toType) {
if (toType.equals(java.sql.Date.class)) {
String[] parameterValue = (String[]) value;
for (DateFormat format:dateFormats) {
try {
return new java.sql.Date(format.parse(parameterValue[0]).getTime());
} catch (ParseException e) {
e.printStackTrace();
}
}
}
return super.convertValue(context, value, toType);
}
}
3.2 、配置转换器
xwork-conversion.properties 创建这么一个文件在WEB-INF下
java.sql.Date=convertor.DateTimeConvertor
3.3、 改一下之前的实例
加一个java.sql.Date;属性在action中。
package action;
import com.opensymphony.xwork2.ActionSupport;
import model.Message;
import java.sql.Date;
/**
* @author JDIT
*/
public class HelloWorldAction extends ActionSupport {
private Message msg;
private Date testDate;
@Override
public String execute() throws Exception {
msg = new Message();
msg.setMessage(this.testDate + "\r" + msg.getMessage());
return SUCCESS;
}
public Message getMsg() {
return msg;
}
public void setMsg(Message msg) {
this.msg = msg;
}
public Date getTestDate() {
return testDate;
}
public void setTestDate(Date testDate) {
this.testDate = testDate;
}
}
3.4、改造下index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Index</title>
</head>
<body>
<center>
<s:form action="hello">
<s:label label="转换器"/>
<s:textfield name="testDate" label="SQL Date"/>
<s:submit value="提交"/>
</s:form>
</center>
</body>
</html>
3.5、 输入日期玩一下
2080-06-77 能转换成功
也就是这里可以把常用的各种日期写法都定义好,这样都能转换成对应的数据类型set到action了。