【工作笔记】Lombok版本变化导致的反序列化异常
Lombok版本变化导致的反序列化异常
背景
因为安全性的考虑,最近在梳理旧系统的系统依赖。改动依赖时候还好,毕竟只是换掉不再合作公司的旧依赖,没敢动别的太多东西。不过没多久,测试团队就找来了…
排查问题之第一次跑偏
旧系统有一些这样的接口(下图,),全部提示异常…
看了下日志,入参对象为空…
2024-12-10 10:11:52,679 [http-nio-9011-exec-3] INFO [xxx.PreservationController:2238] [trace=d900fbccc0932d79] - PolicyReinstatementReqVO(com.xxx.web.vo.endorse.PolicyReinstatementReqVO@17ad, ContNo=null, OrderNo=null)
入参对象如下(注意,都是首字母大写的)
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PolicyReinstatementReqVO implements Serializable {
private static final long serialVersionUID = 6056472621794316031L;
private String ContNo;
private String OrderNo;
}
第一反应就是反序列化出问题了,于是乎,开始查这旧系统的序列化方式。查到了如下配置:
@Bean
public HttpMessageConverter responseBodyConverter() {
MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
List<MediaType> mediaTypeList = new ArrayList<>();
mediaTypeList.add(MediaType.APPLICATION_JSON);
mediaTypeList.add(MediaType.TEXT_HTML);
jackson2HttpMessageConverter.setSupportedMediaTypes(mediaTypeList);
return jackson2HttpMessageConverter;
}
嗯。。用的Jackson(默认大小写敏感的),那就简单了。。改成如下代码
@Bean
public HttpMessageConverter responseBodyConverter() {
MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter(new JacksonMapper());
List<MediaType> mediaTypeList = new ArrayList<>();
mediaTypeList.add(MediaType.APPLICATION_JSON);
mediaTypeList.add(MediaType.TEXT_HTML);
jackson2HttpMessageConverter.setSupportedMediaTypes(mediaTypeList);
return jackson2HttpMessageConverter;
}
// 代码有删减
class JacksonMapper extends ObjectMapper {
public JacksonMapper() {
this.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
}
}
测了下,嗯,问题解决…我果然是个天才~
不过想了下,不对劲
- 我就是改了包依赖…没改代码啊…
- 我这么改看似这个问题解决了…但这种改动在这旧系统会不会引发新问题我也不确定…
- 这旧系统之前是怎么在这看似不合理的情况下正常运行的呢?
所以这么改大概率对但不合适,所以先回滚改动吧…
换个思路排查
- 目前能定位的问题是反序列化时出了问题
- 我的改动就是改了依赖包
综上所属,应该是我改了包依赖之后,导致的问题,而我改依赖包可能导致两个变化。
变化一
删除的三方依赖包有处理序列化的逻辑,我拿咖啡baby看了下源码,完全没有…这里的疑虑排除!
变化二
那就是这里了,错不了,依赖的版本变化导致反序列化出现问题了。
排查问题之第二次跑偏
既然是版本问题,那就查查跟序列化有关的包版本变化有什么变化吧。
旧系统有 jackson、gson、fastjson…
查了老久了,不展开说了(后续的反思也在这里),最后定位跟这些没关系。
Lombok
抓耳挠腮,苦思冥想…没有结果,周会到点了,先开周会去吧…
周会结束重新梳理了下思路:
- 修改依赖导致依赖版本出现了变化
- 依赖版本导致反序列化获取不到属性
- 序列化工具,jackson、fastjson、gson都没问题
那问题是什么呢?抛开序列化工具,无论什么序列化工具都是要回归到对象本身的 getter、setter和 Constructor 的。而我们的这些是通过 Lombok 注解实现的,巧的是,Lombok 的版本也升级了…
先看下前后两个版本的变化吧
// 两个版本的getter、setter是没区别的,但是Constructor有!!!
///新版本:1.18.16
public PolicyReinstatementReqVO(final String ContNo, final String OrderNo) {
this.ContNo = ContNo;
this.OrderNo = OrderNo;
}
// 旧版本:1.16.18
@ConstructorProperties({"ContNo", "OrderNo"})
public PolicyReinstatementReqVO(final String ContNo, final String OrderNo) {
this.ContNo = ContNo;
this.OrderNo = OrderNo;
}
旧版本多了个 @ConstructorProperties,说实话我最开始不知道这个注解是做什么用的…惭愧。于是我先把 Lombok 的版本回退到1.16.18,重新 Run 一下。
ok,问题完美解决。
@ConstructorProperties
- ConstructorProperties 注解是 Java 标准库的一部分。它用于在 Java 的构造函数上,以确保在序列化和反序列化时,构造函数的参数名称和顺序与 JSON 对象中的属性名称和顺序相匹配。并且 @ConstructorProperties 注解的值必须与构造函数参数的顺序相匹配。
- Jackson 库支持 ConstructorProperties 注解。但如果构造函数参数使用了 @JsonProperty 注解,那么 @ConstructorProperties 注解的值可以省略,因为 Jackson 可以直接从 @JsonProperty 注解中获取参数名称。
- 通过使用 @ConstructorProperties 注解,你可以确保 Jackson 在序列化和反序列化时能够正确地处理构造函数参数,从而避免因参数名称不匹配而导致的错误。
反思
好的点 这次处理问题的思路挺好,没有使用自己丰富的想象力天马行空一同胡思乱想,而是一直专注在:(1)问题是什么,(2)是什么变化导致这个问题,这两个点上。
不好的点 处理旧系统之前,虽然没那么多时间完全了解旧系统,但既然要删除三方不安全的依赖,就该提前排查和记录现有的依赖都是什么版本,方便后续的问题追踪。
后续 再研究研究 Spring 以及 Jackson 序列化和反序列化流程吧。这块感觉自己比较熟,但处理问题时又没有那么熟。
原文地址:https://blog.csdn.net/lbh_paopao/article/details/144363517
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!