springmvc绑定Set的解决方案

1、模型

public class Vote {
    private Integer id;
    private String title;
    private Set<VoteItem> voteItems;
    private VoteSubject voteSubject;
}

public class VoteItem {
    private Integer id;
    private String content;
    private Vote vote;
}

2、控制器

    @RequestMapping
    public String vote(@FormModel("votes") Set<Vote> votes) {
        System.out.println(votes);
        return "";
    }

@FormModel注解请参考《扩展SpringMVC以支持更精准的数据绑定1》。

当我们在地址栏输入如:http://localhost:9080/es-web/vote?votes[0].voteItems[0].content=123时,会报:

org.springframework.beans.InvalidPropertyException: Invalid property 'voteItems[0]' of bean class [com.sishuok.es.test.Vote]: Cannot get element with index 0 from Set of size 0, accessed using property path 'voteItems[0]'

3、原因:

原因很明显,Set是无序列表,所以我们使用有顺序注入是不太合适的,BeanWrapperImpl实现:

					else if (value instanceof Set) {
						// Apply index to Iterator in case of a Set.
						Set set = (Set) value;
						int index = Integer.parseInt(key);
						if (index < 0 || index >= set.size()) {
							throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
									"Cannot get element with index " + index + " from Set of size " +
									set.size() + ", accessed using property path '" + propertyName + "'");
						}
						Iterator it = set.iterator();
						for (int j = 0; it.hasNext(); j++) {
							Object elem = it.next();
							if (j == index) {
								value = elem;
								break;
							}
						}
					}

从实现上可以看出,如果set里边有值,那么就能实现绑定。

4、解决方案:

只要保证在springmvc绑定数据之前,给Set里边加上数据即可:

    @ModelAttribute("votes")
    public Set<Vote> initVotes() {
        Set<Vote> votes = new HashSet<Vote>();
        Vote vote = new Vote();
        votes.add(vote);

        vote.setVoteItems(new HashSet<VoteItem>());
        vote.getVoteItems().add(new VoteItem());

        return votes;
    }

这样我们就可以把votes暴露给之前的@FormModel("votes") ,它会使用这个来绑定,所以就有数据了。@ModelAttribute方法请参考《暴露表单引用对象为模型数据》。

但是缺点也很明显,前台必须告诉后台,Set里有几个数据,好让@ModelAttribute方法准备好那么多数据用于数据绑定,比较麻烦。

更简单的解决方案就是使用有序集合,如List,这样最简单

如上方案通用适用于@ModelAttribute的绑定。

最新的@FormModel的实现请到FormModelMethodArgumentResolver.java下载。

相关文章:

扩展SpringMVC以支持更精准的数据绑定1

SpringMVC内置的精准数据绑定2 

猜你喜欢

转载自jinnianshilongnian.iteye.com/blog/1890957
今日推荐