Java springmvc 参数名用is开头导致为null

时间:2024-04-13 19:38:26

因为最近在整理一些源码和编写规范,这里写一下只是记录几年前自己遇到的问题,好久都忘了,还是写下来比较好。

问题记录:由于变量使用了boolean,并且变量名是is开头的,由于java机制boolean默认是false,而参数传递即使为true,在springmvc参数设置的时候,也不会对boolea的is开头的参数做处理,会导致这个值一直是false

原因跟踪:当前端一个请求发过来的时候,请求体是在body里面的,首先,java的boolean值是false
当请求打到controller里面的时候,会先经过springmvc,在AbstractMessageConverterMethodArgumentResolver类的方法【readWithMessageConverters】中进行设置参数,具体路劲和方法如下

org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver#readWithMessageConverters(org.springframework.http.HttpInputMessage, org.springframework.core.MethodParameter, java.lang.reflect.Type)

genericConverter.read做了进一步处理,实际底层调用的是AbstractJackson2HttpMessageConverter类中的read方法,里面获取了java类型等,调用了ObjectMapper,对参数做了序列化处理

在方法中调用了genericConverter.read方法,做了进一步的处理
在这里插入图片描述

接下来要看objectmapper的源码了,这里find的时候,是根据名字isBooleanA来获取对应的值,我们看到现在是有的(因为我的set方法是setIsBooleanA),但是有一种情况会没有,你把你的set方法改成setBooleanA,就没了,如下图所示

在这里插入图片描述
在这里插入图片描述
因为这里为null了,所以就不会invoke参数,所以你的boolean参数,会一直是false,因为java机制,你这里不设置的话,默认false,如果是Boolean,那么就会一直是null

问题来了,_beanProperties为什么这里会拿不到,为null?我参数明明是有的(_beanProperties是BeanPropertyMap实体)

服务起来之后,第一次调用接口,这里会对参数做特殊处理,放入到BeanPropertyMap中,可以看到,boolean值已经变了,我参数名字是isBooleanA,但是这里变成了booleanA

在这里插入图片描述

点的构造方法里面看了下,其实就是参数无法匹配了,这里把参数缓存了,然后你入参请求的时候映射不上了,所以是null
在这里插入图片描述

那么问题来了,是什么原因, 什么时候,把isBooleanA这个变量值改为了booleanA,is去哪里了呢??? 又是什么时候往【_properties】里面放参数的呢???

_properties放值的时候是在BeanDeserializerFactory中的addBeanProps方法中进行的,最下面有个builder.addProperty(prop);,调用了BeanDeserializerBuilder类的addProperty方法,往里面设的值
在这里插入图片描述

而循环用的propDefs参数来自于这里,对入参参数beanDesc.findProperties()进行了特殊处理,然后得到的
在这里插入图片描述

中间省略一万字,直接找beanDesc这个参数是从哪里得到的,如下所示,在这里创建的

com.fasterxml.jackson.databind.deser.DeserializerCache#_createDeserializer

在这里插入图片描述

com.fasterxml.jackson.databind.introspect.BasicClassIntrospector#_findStdTypeDesc这个方法是转换基础数据类型的,实体的话是null,会走得下面的if中,在collectProperties方法中做了处理

在这里插入图片描述
在这里插入图片描述
这里解析出来了get set方法的前缀是什么
在这里插入图片描述

后面继续省略,直接看核心逻辑,直接定位到这里,找他什么时候用反射把数据填进去的,嵌套了一堆,烦死了,找了半天,而且版本也不一样了,之前我都是直接搜coll方法就有,现在还得从新跟源码

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

终于找到了,这个方法原先是coll(),因为我框架版本升级了,变成collectAll()了

在这里插入图片描述
在这里插入图片描述

一直到这里其实都是有的,但是后面有个remove,给删了,就是这个方法,没有匹配的数据,给删了

在这里插入图片描述

框架都是基于反射的,属性的获取和设置,都是基于他的get set方法,有些框架或者使用idea的自动生成get set,都会有一些对参数的特殊处理,比如boolean的is开头参数,会自动把你的is删了,这个时候,由于不符合框架的规则了,就会导致参数无法匹配上。

网上一大堆说怎么处理的,根本原因其实在这里,万物基于反射~~~