Collection和Map支持
WebWork支持多种方法来判断集合中的对象类型. 这是通过一个 ObjectTypeDeterminer 完成的. WebWork提供了缺省实现. 下面的JavaDocs解释了对Map和Collection的支持是如何在DefaultObjectTypeDeterminer中完成的:
ObjectTypeDeterminer检查 Class-conversion.properties 文件中包含的用于表示Map和Collection中包含的对象类型的相关内容 . 对于Collection, 如List, 使用格式 Element_xxx 来指定其中的元素类型, 这里xxx是action或其他对象中的集合属性名称. 对于Map, 需要按照格式 Key_xxx 和 Element_xxx 分别指定key和value的类型.
从WebWork 2.1.x开始, 仍然支持Collection_xxx这样的书写格式, 尽管这种格式已经被声明废弃而且最终将被去除.
(摘自snippet:id=javadoc|javadoc=true|url=com.opensymphony.xwork.util.DefaultObjectTypeDeterminer)
除此之外, 也可以实现接口ObjectTypeDeterminer来创建自己的定制ObjectTypeDeterminer. WebWork也包含一个可选的使用Java5范型(generics)技术实现的ObjectTypeDeterminer. 更多信息参见J2SE 5 Support.
使用集合的属性索引集合元素(Indexing a collection by a property of that collection)
也可以向WebWork传递元素的某个给定属性的值来获取集合中的唯一元素(element). 缺省情况下, 这个属性由 Class-conversion.properties中定义的KeyProperty_xxx=yyy决定, 这里的xxx是返回集合的JavaBean类型名称, yyy是我们用于索引集合中元素的属性名称. (the property of the element of the collection is determined in Class-conversion.properties using KeyProperty_xxx=yyy where xxx is the property of the bean 'Class' that returns the collection and yyy is the property of the collection element that we want to index on.) 下面的两个类是一个示例:
/**
* @return a Collection of Foo objects
*/
public Collection getFooCollection()
{
return foo;
}
/**
* @return a unique identifier
*/
public Long getId()
{
return id;
}
然后将 KeyProperty_fooCollection=id 放在MyAction-conversion.properties文件中. 这样就可以使用 fooCollection(someIdValue) 从集合fooCollection中获取id等于 someIdValue 的Foo对象. 例如, fooCollection(22) 将得到id值为22的Foo对象.
这一点十分有用, 因为这直接将一个集合中的元素与它的唯一标志符联系起来, 而不需要强制使用索引, 从而允许修改一个Bean的集合中的元素而不需要编写额外的代码. 例如, 值为 Phil 的参数 fooCollection(22).name 将集合fooClooection中id属性值为22的Foo对象的name属性设置为"Phil".
Webwork可以使用类型转换自动将参数的类型转换成key属性的类型.
与Map和List元素的属性不同, 如果fooCollection(22)不存在, WebWork不会创建新的对象. 想要做到这一点, 可以使用符号 fooCollection.makeNew[index], 在这里index是一个整数(0, 1等等). 因此, 参数 fooCollection.makeNew[0]=Phil 以及 fooCollection.makeNew[1]=John 将在fooCollection中添加两个新的Foo对象, 一个name属性值为Phil, 另一个为Bar. 注意, 不管用哪种方法, 在使用Set类型时, 必须定义对象的equals方法和hashCode方法来并保证他们不仅仅包含id属性. 这将导致id属性为null的元素可以从Set中删除.
索引的List和Map的高级示例
下面是一个用于List中的模型bean.
该类的KeyProperty是id属性.
public class MyBean implements Serializable {
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String toString() {
return "MyBean{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
下面的action有一个beanList属性, 它被初始化为一个空的ArrayList对象.
ublic class MyBeanAction implements Action {
private List beanList = new ArrayList();
private Map beanMap = new HashMap();
public List getBeanList() {
return beanList;
}
public void setBeanList(List beanList) {
this.beanList = beanList;
}
public Map getBeanMap() {
return beanMap;
}
public void setBeanMap(Map beanMap) {
this.beanMap = beanMap;
}
public String execute() throws Exception {
return SUCCESS;
}
}
定义在conversion.properties中的内容告诉TypeConverter使用MyBean的实例作为List的元素.
KeyProperty_beanList=id
Element_beanList=MyBean
CreateIfNull_beanList=true
当通过表单提交到Action时, (id)的值被当作beanList中MyBean实例的KeyProperty.
注意()符号! 不要使用[], 那仅能用在Map里!
属性的name的值将根据指定的id设置到对应的MyBean实例中.
无效的id值将不会再加入null值.
这就避免了OutOfMemory异常的产生!
<ww:iterator value="beanList" id="bean">
<ww:textfield name="beanList(%{bean.id}).name" />
</ww:iterator>