Struts2的类型转换详解

来源:互联网 发布:淘宝品质退款率 编辑:程序博客网 时间:2024/05/22 15:21

Struts2内建了十分强大的类型转换机制,用于将表现层获得的数据转换成web应用后台所需要的数据类型。同时,Struts2提供了良好的扩展性,开发者可以非常简单的开发出自己的类型转换器,完成字符串和自定义复合类型之间的转换。同时,如果类型转换出现了异常,开发者无需关系异常处理罗技,内建的conversionError拦截器会自动拦截并处理该异常。

1.Struts2内建的类型转换器

Struts2内奸了字符串类型到如下类型之间转换的转换器:
boolean和Boolean:完成字符串和布尔值之间的转换;
char和character:完成字符串和字符之间的转换;
int和Integer:完成字符串和整型之间的转换;
long和Long:完成字符串和长整型之间的转换;
float和Float:完成字符串和浮点型之间的转换;
double和Double:完成字符串和双浮点之间的转换;
Date:完成字符串和日期之间的转换;
数组:默认情况下,数组类型是字符串,如果用户提供了自定义类型转换器,也可以是其他类型的数组
集合:默认情况下,集合的元素类型是String,创建一个新的ArrayList封装所有的字符串。

1.1基于OGNL的类型转换

struts可以基于OGNL表达式来完成类型转换。一个简单的例子就是下面的例子。user.username就是OGNL表达式的形式;
<s:form action="loginAction"><s:textfield name="user.username" key="user"/><s:password name="user.password" key="pass"/><s:submit key="login" /></s:form>
对于LoginAction对应的class源代码如下所示:
public class LoginAction extends ActionSupport{private User user;public String getUser() {return user;}public void setUser(User user) {this.user = user;}public String execute() throws Exception{}}

通过这种方式,Struts2可以将普通请求参数转换成复合类型对象,但是使用的时候有两点需要注意:
1.因为Struts2通过反射来创建一个复合类的实例,因此系统必须为该复合类提供无参数构造器;
2.如果希望使用user.username请求参数的形式为Action实例的user属性的name属性赋值,则必须为user属性对应的复合类(User类)提供setName()方法,因为Struts2是通过调用该方法为该属性赋值的。这就叫做依赖注入!

利用这种形式,我们甚至可以直接生成Collection实例。如何做请见下面的例子
1.创建map实例
我们在对应的Action里面创建一个map:Map<String,User> users;
在对应的表单中,写下如下语句<s:textField name="users['one'].name />
<s:textField name="users['one'].pass />
<s:textField name="users['two'].name />
<s:textField name="users['two'].pass />
表单textField域中,name属性的形式就是map的形式。其中users代指map实例,one和two是map的key,这里是String类型的。name和pass是对应user的名和密码。这里的name和pass必须在User.java这个类里面也是这个名字,并设置Setter和Getter。
2.创建list实例

我们在对应的Action里面创建一个list:list<user> users;
在对应的表单中,写下如下语句<s:textField name="users[0].name />
<s:textField name="users[0].pass />
<s:textField name="users[1].name />
<s:textField name="users[1].pass />
和map不同的是,这里应该使用的是下标,是数字,而不是字符串。

1.2指定集合元素的类型

前面我们使用集合时都是用了泛型,这种泛型可以让Struts2了解集合元素的类型。问题是,如果不使用泛型,Struts2还知道使用类型转换器来处理users属性吗?当然不知道。因此,我们需要用到一个局部类型转换文件,提供相应的类型转换配置信息。
这个类型转换文件的名字必须为ActionName-conversion.properties的形式,表示与一个Action对应。比如我们上面的LoginAction的例子,我们把List的泛型User去掉,那么这个时候就需要在这个配置文件里面配置了。
配置文件是由若干键值对构成的,键值对的形式如下(map类型需要指定两个,分别是key和map):
Element_<ListPropName>=<ElementType>//list
Key_<MapPropName>=<keyType>//for map
Element_<MapPropName>=<valueType>//for map
还是上面的例子,对于一个list类型的users,我们没有指定泛型为User,那么这个时候配置文件的内容应该是:
Element_users=com.nju.User
其中com.nju.User为具体类的报名加类名。

2.自定义类型的转换器

2.1实现转换器

对于一些特殊的类型转换,Struts2并没有内建类型转换器,这个时候不要担心。Struts2良好的拓展机制给了我们写自定义类型转换器的机会。下面我们做一个简单的例子实现类型转换器。
假设用户输入一个字符串abc,xyz,其中abc是用户名,xyz是用户的密码。对于这个字符串 ,Struts2应该怎么处理才能得到一个User类型的对象呢?
public class LoginAction extends ActionSupport{private User user;public String getUser() {return user;}public void setUser(User user) {this.user = user;}public String execute() throws Exception{}}
要想实现自定义转换器,我们必须实现对应的TypeConverter接口,但是TypeConverter接口的convertValue方法包含6个参数,实在复杂。我们可以通过继承该接口的一个实现类来重写我们的convertValue方法。
public class UserConverter extends DefaultTypeConverter{public Object convertValue(Map context,Object value,Class 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{User user = new User();user.setPassword("123");user.setUsername("abc");return user;}}}
对于convertValue()方法,里面包含三个参数,这三个参数的含义如下:
context:类型转换环境的上下文;
value:是需要转换的参数,也就是我们需要把value转换成对应的类型;或者value已经是对应的类型,要将value转换成字符串
toType:是转换后的目标类型。

下面就是配置我们的转换器了,要想让转换器起作用,我们必须在局部类型转换器中添加如下格式的一行代码:<propName>=<convertClass>。
比如本例就是user=cn.nju.UserConverter;
这个文件就是前文提到的局部类型转化器文件,文件的名字为:LoginAction-conversion.properties。这个文件必须和对应的Action放在同一个包底下,不然会不起作用。

2.2全局自定义类型转换器的注册方式

局部类型转换器的注册,在上文已经提到,只需要在局部类型转换文件中添加一行即可。主要要和对应Action放到同一个包。
但是,局部类型转换器有其局限性,就是这个转化器只能适用于当前Action,对于其他的Action,万一用到同样的类型,则需要更多的局部类新转化文件。那么我们可以采取全局的方式。
我们需要在src下创建一个xwork-conversion.properties文件,然后逐一添加对应的类型与对应的转换器,格式和局部类型转化器不太一样,是<propType>=<convertClass>。
比如cn.nju.User=cn.nju.UserConverter。

3基于Struts2的自定义类型转换器

为了简化类型转换器,不适用toType判断转化的方向,Struts2提供了一个StrutsTypeConverter抽象类,这个类是DefaultTypeConverter的子类。这个类已经实现了DefaultTypeConverter的convertValue()方法,实现的过程中,它将两个不同的方向替代为两个不同的方法。我们只需要新建一个我们自己的MyConverter继承StrutsTypeConverter,覆盖这两个方法即可。如下例
public class UserConverter2 extends StrutsTypeConverter{@Overridepublic Object convertFromString(Map context, String[] value, Class toClass) {User user = new User();String param=value[0];String[] userValues=param.split(",");user.setUsername(userValues[0]);user.setPassword(userValues[1]);return user;}@Overridepublic String convertToString(Map context, Object value) {// TODO Auto-generated method stubUser user = (User)value;return user.getUsername()+","+user.getPassword();}}




0 0
原创粉丝点击