欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

springmvc绑定Set的解决方案

程序员文章站 2022-03-02 08:49:23
...

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