4.5.1 指定集合元素的类型

本节介绍的知识点比较“罕见”,这是Struts 2为了照顾那些Java 5以前的读者而提供的支持。Java 5以前的Java版本并没有提供泛型支持,此时Action类的代码片段如下。

程序清单:codes\04\4.5\Element_Type\WEB-INF\src\org\crazyit\struts2\action\LoginAction.java

public class LoginAction implements Action
{
    // users属性没有泛型
    private List users;
    // users属性对应的setter和getter方法也取消泛型定义
    public void setUsers(List user)
    {
          this.user = user;
    }
    public List getUsers()
    {
          return this.users;
    }
    // 省略了代码的其他部分
    ...
    // 处理请求的execute方法
    public String execute() throws Exception
    {
          //因为取消了泛型,必须执行强制类型转换
          if (((User)getUser().get(0)).getName().equals("crazyit")
                && ((User)getUser().get(0)).getPass().equals("leegang") )
          {
                ...
          }
          ...
    }
}

对于上面的users属性,系统根本不清楚 List里元素的类型。此时可能发生如下两种情况。

如果程序使用局部类型转换器,由于局部类型转换器对Action的指定属性起作用(无须理会该List集合元素的类型),因此局部类型转换器依然可以正常工作。

如果程序使用全局类型转换器,由于全局类型转换器是对指定类型起作用,系统现在不知道List集合元素的类型,因此全局类型转换器将无法正常进行转换。

为了让系统知道List里的元素类型,为了让系统的类型转换器起作用,有两种方法。

使用泛型来限制集合里元素的类型:前面的应用都使用了泛型来限制集合元素的类型。

使用Struts 2的配置文件:在局部类型转换配置文件中指定集合元素的数据类型。

使用泛型来限定集合元素的类型当然是一种较好的做法,如果不能使用泛型,Struts 2允许在局部类型转换文件中增加如下的key-value对:

Element_xxx=集合元素类型

上面key-value对中的Element是固定的,xxx是Action中的集合属性名,复合类型是集合元素类型的全限定类名(应该包括完整的包前缀)。

为了让本应用可以正常运行,系统需要增加一个LoginAction-conversion.properties文件,该文件与LoginAction类的class文件放在同一个地方。该文件的代码如下:

# 指定Action类的users集合属性的元素类型为org.crazyit.struts2.domain.User
Element_users=org.crazyit.struts2.domain.User

增加定义后,系统将可以识别到 users 集合属性的集合元素是 org.crazyit.struts2.domain. User类型,相应的类型转换器将可以对该属性生效。

对于Map类型的属性,则需要同时指定Map的key类型和value类型。为了指定Map类型属性的key类型,应该在局部类型转换文件中增加如下项:

Key_xxx=key元素类型

其中,Key是固定的,xxx是Map类型属性的属性名,复合类型指定的是Map属性的key类型的全限定类名。

为了指定Map类型属性的value类型,应该在局部类型转换文件中增加如下项:

Element_xxx=value元素类型

其中,Element是固定的,xxx是Map类型属性的属性名,复合类型指定的是Map属性的value类型的全限定类名。

通过上面的局部类型转换元素指定集合元素类型后,系统的类型转换器将可以正常工作。为了在JSP页面中输出List属性的某个元素的值,可以使用如下格式:

<s:property value="集合属性名[索引].集合元素属性名"/>

下面是JSP页面中输出Action实例中属性的代码片段。

<!-- 如下四行输出集合元素的属性值 -->
用户1的用户名为:<s:property value="users[0].name"/><br />
用户1的密码为:<s:property value="users[0].pass"/><br />
用户2的用户名为:<s:property value="users[1].name"/><br />
用户2的密码为:<s:property value="users[1].pass"/><br />
<!-- 如下一行输出Action的普通属性值 -->
生日为:<s:property value="birth"/><br>

但是,对于Set类型的属性则无法通过索引访问集合元素——因为Set是无序集合。幸好, Struts 2还提供了一个指定索引属性的方法。