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下载。
相关文章:
推荐阅读
-
vue 中this.$set 动态绑定数据的案例讲解
-
SpringMVC中利用@InitBinder来对页面数据进行解析绑定的方法
-
记一次springMVC的跨域解决方案
-
springmvc代码详细(五种映射,绑定参数,处理json数据,文件上传,转发,拦截器的实现)
-
JavaScript ECAMScript5 特性get/set访问器 实现json数据与dom对象的绑定
-
vue 使用 v-model 双向绑定父子组件的值遇见的问题及解决方案
-
SpringMVC学习(二):参数的绑定及常用注解
-
jquery 新建的元素事件绑定问题解决方案
-
Vue + Spring Boot——axios使用GET以参数的方式传递对象到SpringMVC解决方案
-
springmvc中下载中文文件名称为下划线的解决方案