前言
踩了个lombok的坑,记录一下经过。
问题出现
日常排查bug的时候发现一个诡异的问题,json入参到了controller的方法内部,对应的实体对象有个字段一直是空值
排查经过
因为字段在进入controller方法之前就已经为空了,所以要在请求处理的更早的阶段定位问题,通过在springMVC源码里面打断点调试来排查
终于,在层层方法调用之后,在AbstractMessageConverterMethodArgumentResolver 的readWithMessageConverters 方法里面找到了关键的代码
这里调用 AbstractJackson2HttpMessageConverter 的 read 方法将请求数据转换成接口入参对应的实体对象,查看这个方法的返回结果发现,在这里的时候接口实体类的对应字段就是空值了
到这里,基本可以将问题锁定在这个方法内部。 继续调用,进入ObjectMapper的 _readMapAndClose 方法,发现反序列化器 JsonDeserializer 中解析到的的属性字段为 tcompanyBillConfigId ,实体类中定义的字段为 tCompanyBillConfigId ,这里就是导致字段反序列化为空的直接原因。
通过层层排查,最终在POJOPropertiesCollector的collectAll方法中发现了问题所在,该方法是收集实际属性信息的内部方法。如下图所示该方法收集到 tCompanyBillConfigId 和 tcompanyBillConfigId 两个属性。
默认情况下,该方法会从字段和 getter , setter 方法获取属性,根据上图,分别从tCompanyBillConfigId 字段 获取到了属性 tCompanyBillConfigId
和 getTCompanyBillConfigId 方法获取到了属性 tcompanyBillConfigId
在 _removeUnwantedProperties 方法中,属性 tCompanyBillConfigId由于是从 private 字段获取的,并且没有(不是真的没有,而是反序列化器认为没有)对应的 setter 和 getter 方法,被移除。
为什么从 tCompanyBillConfigId 字段 和 getter setter 方法会得到两个属性呢?
查看 idea 反编译 class 文件的结果,可以看到 lombok 生成的 getter setter 方法名将字母 t 变成了大写,对比下图用 idea 辅助生成的 setter getter 方法可以看出区别
总结
1. 字段命名需要更加规范
2. lombok 使用需谨慎