ActionForm中动态长度的List

转载自http://qingbo.net/blog/post322.html 

某些情况下,一个表单中提交的内容数量是不一定的。比如Facebook的编辑照片界面,可以把整个相册的照片(最多60张)放在一起进行批量编辑,或者把一次上传的若干张照片一起编辑。这种情况下,如何用ActionForm来获取这些数据呢?

这个ActionForm(假设名为PhotoForm)应该有一个字段:

List<Photo> photos;

生成这个表单的时候很简单,服务器端当然清楚有多少张照片要被编辑,于是对这些照片遍历一遍,生成表单。实际上,struts form的设计考虑了链表数据的提交。以照片编辑页面为例,生成表单时,可以这样:

<logic:iterate id=”photo” name=”photos”>
<html:hidden name=”photo” property=”id” indexed=”true” />
<html:text name=”photo” property=”name” indexed=”true” />
</logic:iterate>

indexed属性便是专为链表设计的。这样的jsp代码生成的HTML类似:

<input type=”hidden” value=”5″ name=”photo[4].id”/>
<input type=”text” value=”编辑前的名字” name=”photo[4].name”/>

然而在用户将修改过的信息提交的时候,由于HTTP协议的stateless特性,服务器端已经“忘记”有多少张照片了(除非你在session中记录了这个数字,不过处于性能考虑大多数人在避免使用session,另外,假如用户在编辑信息的途中出去玩了几小时,回来继续提交的话,session已经不存在了)。

photos这个List即使放在对应的ActionForm中也无济于事,因为用户看到表单时,这个ActionForm对象已经消失了(当然,不要在那个mapping中设置scope=”session”)。

究其源,溯其本,很容易解决这种问题。请求提交给struts,struts首先根据mapping创建一个对应的ActionForm对象,当它看到表单中的属性名为photo[4].id,就会调用PhotoForm的getPhoto(4).setId(xxx)来填充表单。

注意,struts不是生成一个Photo对象,把id、name填充进去,再加到photos这个List中,它不知道要生成Photo对象。它只知道利用发射机制调用getPhoto(4).setId(xxx)。

所以我们应该在PhotoForm的getPhoto这个方法里做文章,根据参数将List扩展到适当的大小避免IndexOutOfBoundException,并且生成Photo对象保证不出现NullPointerException. 示例如下:

public Photo getPhoto(int index) {
	// 如果链表不存在则创建
	if (photos == null) {
		photos = new ArrayList<Photo>(index + 1);
	}

	// 如果链表长度不够,扩展
	if (photos.size() < index + 1) {
		for (int i = photos.size(); i < index + 1; i++) {
			photos.add(null);
		}
	}

	// 取得photo,如果为空则创建
	Photo photo = photos.get(index);
	if (photo == null) {
		photo = new Photo();
		photos.set(index, photo);
	}
	return photo;
}

这样就可以了,没有用到session. 看起来比较繁琐,其实道理很简单,明白了struts form的填充方式,就没什么困难了。

另一个例子是客户端可以用JavaScript生成一堆这样的file input:

<input type=”file” name=”file[0]” />
<input type=”file” name=”file[1]” />
<input type=”file” name=”file[2]” />
<input type=”file” name=”file[3]” />

struts怎么填充呢?它会首先读取文件数据,创建FormFile对象,然后调用对应的ActionForm的setFile(index, file)方法填充,index就是那个“数组下标”。所以你需要写一个setFile方法来正确处理。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值