使用 SpringBoot2 + spring-data-redis 做缓存 ,GenericFastJsonRedisSerializer 做序列化和反序列化的情况下,devtools 开启本地热部署后,导致异常出现:

java.lang.ClassCastException: DTOObject cannot be cast to DTOObject

某个类不能强制转换成某个类,但是这两个类确实是一模一样的,错误主要出现在类加载器上

首先,出现这个问题,因为类的全名和路径都一样,那么根据java判断两个类是否是同一个类的2个原则:全名和类加载器,所以这个问题肯定是由类加载器不同引起的。由于使用 devtools 开启了热部署后,RestartClassLoader 目的是用于开发的时候,修改了类之后项目的快速重启和重载,导致了两个类无法转换

Stackoverflow 上的求助 也没有提供有效的解决办法

解决方式一

不开启 devtools ,也就是热部署,注释代码

<!-- 
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-devtools</artifactId>
  <optional>true</optional>
</dependency>
-->

这种办法最直接最快,但是体验最不好,全网搜出来也差不多是这种,注释后,无法热部署,开发很头疼,这种方式坚决不推荐!

解决方式二

SpringBoot Devtools 官方文档有说明,自定义重启类加载器

创建一个 META-INF/spring-devtools.properties 文件:

WX20200430-151940@2x.png

该 spring-devtools.properties 文件可以包含以 restart.exclude 和开头的属性 restart.include 。该include元素是应该被拉高到“重启”的类加载器的项目,以及 exclude 要素是应该向下推入“基地”类加载器的项目。该属性的值是一个应用于类路径的正则表达式模式,如以下示例所示:

restart.exclude.companycommonlibs=/mycorp-common-[\\w\\d-\.]+\.jar
restart.include.projectcommon=/mycorp-myproj-[\\w\\d-\.]+\.jar

第一时间想到的是加入以下代码:

restart.include.cache=/spring-data-redis-.*.jar

配置 redis 相关类的重启,但是报错了,项目都启动不了。

后来,转头一想,应该是从 redis 取出缓存使用 GenericFastJsonRedisSerializer 做反序列化的时候转换类型报错,所以应该将 fastjson include 重启中,如下:

restart.include.json=/com.alibaba.fastjson.*.jar

重启项目后就可以解决 SpringBoot2 开启 spring-boot-devtools 插件热部署 使用 springboot-data-redis 在反序列化的时候报错 java.lang.ClassCastException: DTOObject cannot be cast to DTOObject 的问题了

此处我使用的是:GenericFastJsonRedisSerializer 做序列化和反序列化,其它类视情况更改

首发于:AOMAO

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐