前言
所有的MVC框架,都需要负责解析HTTP请求参数,并将请求参数传给控制器组件。这个时候就会出现一个问题:HTTP请求参数都是字符串类型,而Java是强类型的语言,因此MVC框架必须将这些字符串参数转换成相应的数据类型。是的,这些繁琐的工作都需要MVC框架来完成。
Struts2框架提供了非常强大的类型转换机制。有很多内建的类型转换器在默默的工作,也有基于OGNL表达式的转换机制,还有我们可以自定义我们自己的类型转换器。在Struts2框架中,一切都是很简单的,用起来很爽的,就是如此惬意。
内建的类型转换器
对于大部分的常用类型,开发者无须理会类型转换,Struts2可以完成大多数常用的类型转换。这些常用的类型转换是通过Struts2内建的类型转换器完成的,Struts2框架已经内建了字符串类型和以下这些类型之间相互转换的转换器:
- boolean和Boolean:完成字符串和布尔值之间的转换
- char和Character:完成字符串和字符之间的转换
- int和Integer:完成字符串和整型值之间的转换
- long和Long:完成字符串和长整型值之间的转换
- float和Float:完成字符串和单精度浮点值之间的转换
- double和Double:完成字符串和双精度浮点值之间的转换
- Date:完成字符串和日期类型之间的转换
- 数组:在默认情况下,数组元素是字符串,如果用户提供了自定义类型转换器,也可以是其它复合类型的数组
- 集合:在默认情况下,集合元素时字符串,并创建一个新的ArrayList封装所有的字符串
下面就通过代码来简单看看如何使用这些内建的类型转换器是否可以很好的完成我们的工作。
<form action="login" method="post">
姓名: <input type="text" name="name"><br>
性别: <input type="radio" name="sex" value="M">Male
<input type="radio" name="sex" value="F">Female<br>
年龄: <input type="text" name="age"><br>
喜欢的编程语言:
<input type="checkbox" name="language" value="C++">C++<br>
<input type="checkbox" name="language" value="Java">Java<br>
<input type="checkbox" name="language" value="Lua">Lua<br>
<input type="checkbox" name="language" value="Python">Python<br>
<input type="checkbox" name="language" value="C#">C#<br>
计算题:4/3等于:
<input type="text" name="result"><br>
<input type="submit" value="Submit">
</form>
我们在对应的Action中,可以这样定义:
private String name;
private char sex;
private int age;
private String[] language;
private float result;
我们不用考虑如何将字符串转成char类型、int类型、或者float类型,这些都已经由Struts2框架完成了,这就是内建的类型转换器所完成的工作。
基于OGNL的类型转换
使用内建的类型转换器的确能帮助我们完成很多工作,但是很多时候,我们的Action类并不会只包含一些内建类型那么简单,而是会包含一些符合类型,比如User类的实例user等。那么如何将请求参数转换成User这种复合类型呢?此时,使用基于OGNL的类型转换器,就可以很方便的将请求参数转换成类似于User这种复合类型。下面通过一个例子来说明如何使用OGNL表达式来完成这个任务。比如有这么个Action类,其中的主要代码如下:
private User user; // 这是一个复合类型
private String tip;
public void setUser(User user)
{
this.user = user;
}
public User getUser()
{
return user;
}
public void setTip(String tip)
{
this.tip = tip;
}
public String getTip()
{
return tip;
}
关键的前台页面代码如下:
<form action="login" method="post">
用户名:<input type="text" name="user.name"><br>
密 码:<input type="password" name="user.password"><br>
<input type="submit" value="Submit">
</form>
可以看到,Action类里有一个User类型的属性,这个属性需要进行类型转换,Struts2框架接受到HTTP请求参数后,需要将这些请求参数封装成User对象。再仔细看看前台页面代码,可以发现请求参数名并不是普通参数名,而是user.name
和user.password
的形式,这就是OGNL表达式的形式。Struts2会把user.name
参数的值赋值给Action实例的user属性的name属性,并将user.password
参数的值赋值给Action实例的user属性的password属性。
通过这种方式,Struts2可以将普通请求参数转换成复合类型对象,但在使用这种方式时有如下两点需要注意:
- 因为Struts2将通过反射来创建一个复合类的实例,因此系统必须为该复合类提供无参数的构造器;
- 如果希望使用
user.name
请求参数的形式为Action实例的user属性的name属性赋值,则必须为user属性对应的复合类提供setName()
方法,因为Struts2是通过调用该方法来为该属性赋值的。
对于集合,我们依然可以使用OGNL的方式来进行类型转换,具体请看下面这个例子:
private Map<String, User> users; // 这是一个复合类型
public void setUsers(Map<String, User> users)
{
this.users = users;
}
public Map<String, User> getUsers()
{
return users;
}
JSP页面代码如下:
<form action="login" method="post">
第一个用户名:<input type="text" name="users['one'].name"><br>
第一个用户密码:<input type="password" name="users['one'].password"><br>
第二个用户名:<input type="text" name="users['two'].name"><br>
第二个用户密码:<input type="password" name="users['two'].password"><br>
<input type="submit" value="Submit">
</form>
在使用集合的时候,一定需要指明集合中元素的类型,上面的代码就是通过泛型的方式来指定了子元素的类型。;这种使用泛型可以让Struts2知道集合中元素的具体类型,Struts2就可以通过反射来创建对应类的对象,并将对象添加到Map中。
总结
这篇文章对Struts2框架中的类型转换器进行了大致的总结,主要从以下两个方面进行的总结:
- 内建类型转换器
- 基于OGNL表达式的类型转换器
内建的类型转换器在平时开发中经常被忽视,但是我们需要知道它的存在;而基于OGNL表达式的类型转换器则是一把称心如意的武器,可以大大提高开发效率。
果冻想,认真玩技术的地方。
2016年3月16日 于呼和浩特。