SpringMVC代码碎片拾遗(01)_一个SpringMVC中对于领域模型绑定的不注意错误
2015-04-20 23:10
295 查看
最近这个项目真是各种问题猛喷发,呵呵。
SpringMVC的各种运用不用说了,而更多的需要把底层重写的地方就成为了这个架构的亮点。
害怕Session风暴而使用MongoDB的值传递方式虽然比较奇葩但是的确是有点特色,不过问题来了,绑定参数处理的Resolver都需要自己重写咯。。。
这些后面慢慢记录。
先说一个某天晚上特别诡异的问题,死活查不到原因,后来跟踪代码才发现的问题吧。(其实是一个特别低级的错误,没仔细看自己的业务层直接扒开源代码看了半天
是夜,HN同学正在把他那一个超级大的功能模块进行测试,第一个按钮就直接exception了。
看到后,一个反应就是画面上或者后来的逻辑有越界的地方,当时没细看出错地点。大概看了一下代码觉得没有任何问题。仔细一看出错地点,嗯?居然是spring的BeanWrapperImpl抛出来的问题。这个Class是大名鼎鼎的数据绑定的类,一般Controller的参数的绑定默认都是在这个Class中进行的invoke操作,这个类非常内聚,很多core的功能都在这个类中实现完成。曾经看过这个Class想过读一下代码,但是读源代码如果没有一个特定使用环境总觉得读一会就要睡着的节奏。这次看来是逃不过去了。
错误如下:
其中inputList是我们自己做成的Form中的一个filed,存储的事画面上的一个循环List。当时没有好好看这段Log,只是看到了BeanWrapperImpl就开始跟踪源代码了。。。
出错的地方在:
代码拿到手刚开始没太看明白。。。当时已经22:00多,直接跟踪了一下恍然大悟。
首先,对于我们需要绑定的数据内容,spring会根据其基本的类型采取不同的方式来获得数据(具体调用过程比较复杂,后面写文章再说),这里走到了list的这个选择分支。那么代码中是value = list.get(index); 来进行的获取,从第一个数据开始取得那么就是要get(0),但是发现get(0)直接就出上面的错误。然后发现了在这个调用前还有一个growCollectionIfNecessary的方法,这个方法貌似有些作用。
方法中其实很简单isAutoGrowNestedPaths()能过的话(今后讨论这个方法),下面是进行了一个往插入一个object的操作。
其中newValue可以直接反射出以elementType为对象的一个Bean,而这个elementType是啥?就是GenericCollectionTypeResolver.getCollectionReturnType(pd.getReadMethod(), nestingLevel);取得的一个泛型类型,是通过pd这个参数传进来的,pd直接掌握着需要绑定的这个对象的内部的信息,比如其拥有的泛型内容是什么。
看到这里,恍然大悟,错误的原因是我们根本没有在自己的Form中给这个inputList设置DTO泛型,导致经过growCollectionIfNecessary方法后,list中并没有塞入任何东西,所以就out of bound了。。。
按说如果刚开始好好看看Log的话一下子应该也能明白,半夜的脑子的确不行了。
减少加班,远离加班。。。
SpringMVC的各种运用不用说了,而更多的需要把底层重写的地方就成为了这个架构的亮点。
害怕Session风暴而使用MongoDB的值传递方式虽然比较奇葩但是的确是有点特色,不过问题来了,绑定参数处理的Resolver都需要自己重写咯。。。
这些后面慢慢记录。
先说一个某天晚上特别诡异的问题,死活查不到原因,后来跟踪代码才发现的问题吧。(其实是一个特别低级的错误,没仔细看自己的业务层直接扒开源代码看了半天
是夜,HN同学正在把他那一个超级大的功能模块进行测试,第一个按钮就直接exception了。
看到后,一个反应就是画面上或者后来的逻辑有越界的地方,当时没细看出错地点。大概看了一下代码觉得没有任何问题。仔细一看出错地点,嗯?居然是spring的BeanWrapperImpl抛出来的问题。这个Class是大名鼎鼎的数据绑定的类,一般Controller的参数的绑定默认都是在这个Class中进行的invoke操作,这个类非常内聚,很多core的功能都在这个类中实现完成。曾经看过这个Class想过读一下代码,但是读源代码如果没有一个特定使用环境总觉得读一会就要睡着的节奏。这次看来是逃不过去了。
错误如下:
org.springframework.beans.InvalidPropertyException: Invalid property 'inputList[0]' of bean class [xx.xx.xx.xx.online.xx.xx.xxx]: Index of out of bounds in property path 'inputList[0]'; nested exception is java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 at org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:812) ~[BeanWrapperImpl.class:4.1.0.RELEASE] at org.springframework.beans.BeanWrapperImpl.getNestedBeanWrapper(BeanWrapperImpl.java:551) ~[BeanWrapperImpl.class:4.1.0.RELEASE] at org.springframework.beans.BeanWrapperImpl.getBeanWrapperForPropertyPath(BeanWrapperImpl.java:528) ~[BeanWrapperImpl.class:4.1.0.RELEASE] at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:892) ~[BeanWrapperImpl.class:4.1.0.RELEASE] at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:95) ~[AbstractPropertyAccessor.class:4.1.0.RELEASE] at org.springframework.validation.DataBinder.applyPropertyValues(DataBinder.java:728) ~[DataBinder.class:4.1.0.RELEASE] at org.springframework.validation.DataBinder.doBind(DataBinder.java:624) ~[DataBinder.class:4.1.0.RELEASE] at org.springframework.web.bind.WebDataBinder.doBind(WebDataBinder.java:189) ~[WebDataBinder.class:4.1.0.RELEASE]
其中inputList是我们自己做成的Form中的一个filed,存储的事画面上的一个循环List。当时没有好好看这段Log,只是看到了BeanWrapperImpl就开始跟踪源代码了。。。
出错的地方在:
else if (value instanceof List) { int index = Integer.parseInt(key); List<Object> list = (List<Object>) value; growCollectionIfNecessary(list, index, indexedPropertyName, pd, i + 1); value = list.get(index); // 这个地方只要get(0)就直接出错了 } private void growCollectionIfNecessary(Collection<Object> collection, int index, String name, PropertyDescriptor pd, int nestingLevel) { if (!isAutoGrowNestedPaths()) { return; } int size = collection.size(); if (index >= size && index < this.autoGrowCollectionLimit) { Class<?> elementType = GenericCollectionTypeResolver.getCollectionReturnType(pd.getReadMethod(), nestingLevel); if (elementType != null) { for (int i = collection.size(); i < index + 1; i++) { collection.add(newValue(elementType, name)); } } } }
代码拿到手刚开始没太看明白。。。当时已经22:00多,直接跟踪了一下恍然大悟。
首先,对于我们需要绑定的数据内容,spring会根据其基本的类型采取不同的方式来获得数据(具体调用过程比较复杂,后面写文章再说),这里走到了list的这个选择分支。那么代码中是value = list.get(index); 来进行的获取,从第一个数据开始取得那么就是要get(0),但是发现get(0)直接就出上面的错误。然后发现了在这个调用前还有一个growCollectionIfNecessary的方法,这个方法貌似有些作用。
方法中其实很简单isAutoGrowNestedPaths()能过的话(今后讨论这个方法),下面是进行了一个往插入一个object的操作。
collection.add(newValue(elementType, name));
其中newValue可以直接反射出以elementType为对象的一个Bean,而这个elementType是啥?就是GenericCollectionTypeResolver.getCollectionReturnType(pd.getReadMethod(), nestingLevel);取得的一个泛型类型,是通过pd这个参数传进来的,pd直接掌握着需要绑定的这个对象的内部的信息,比如其拥有的泛型内容是什么。
看到这里,恍然大悟,错误的原因是我们根本没有在自己的Form中给这个inputList设置DTO泛型,导致经过growCollectionIfNecessary方法后,list中并没有塞入任何东西,所以就out of bound了。。。
按说如果刚开始好好看看Log的话一下子应该也能明白,半夜的脑子的确不行了。
减少加班,远离加班。。。
相关文章推荐
- 《互联网领域Java从来就不是主流》一个完全错误的标题!炒作短时间带来了流量,却损害了作者的声誉,推荐人的信誉,以及读者对于网站的期待。
- UserControl 的一个值得注意的问题 [属性" * "的代码生成失败.错误是:"程序集"*.Version=1.0.0.0,Culture=neutral,..........无标记为序列化"
- 领域建模有很多种方法,对于同样的问题域使用不同的建模手段得到的模型可能也不尽相同。于是我经常听到这样一个问题:怎么才能保证建模的正确性?
- UserControl 的一个值得注意的问题 [属性" * "的代码生成失败.错误是:"程序集"*.Version=1.0.0.0,Culture=neutral,..........无标记为序列化"
- Springmvc关于拦截所有网址的一个致命错误,需注意!
- SpringMVC3,使用RequestMappint的Param参数,实现一个url绑定多个方法
- Laravel之路由 Route::get/post/any、路由参数、过滤器、命名、子域名、前缀、与模型绑定、抛出 404 错误、控制器
- 模型生成过程中检测到一个或多个验证错误
- 数据绑定应当注意的一个白痴问题
- SpringMVC绑定到实体数组、list、set、和map时要注意
- (转)一个简单例子:贫血模型or领域模型
- 对于中英文的处理,错误码的处理,还有其它处理的代码
- ArcGIS 帮助文档行内模型变量替换的示例的一个错误
- 发布一个小工具:建立站点和域名绑定(附代码)
- Online Coding开发模式 (通过在线配置实现一个表模型的增删改查功能,无需写任何代码)
- 对于一个表中字段保存的是代码,怎么用Struts+Hibernate将名称显示出来
- Hadoop学习笔记—4.初识MapReduce 一、神马是高大上的MapReduce MapReduce是Google的一项重要技术,它首先是一个编程模型,用以进行大数据量的计算。对于大数据
- 一个问题阻止windows正确检查此机器的许可证 错误代码:0x80070002
- 一个简单的echo服务模型(最原始版本,代码没有优化)
- ?一个XML对象在javascript中调用的代码错误