java.lang.ClassCastException: DTO 对象无法转换为 DTO 对象
java.lang.ClassCastException: DTOObject cannot be cast to DTOObject
我的应用程序在 Spring Boot 1.4.0M3 上运行时遇到一个奇怪的问题,它使用 Spring 缓存实现,其中提供程序是 Redis,我收到 classCastException 无法转换相同的对象
我正在使用 Mongodb 作为数据库,我有用户对象,其中包含延迟加载的角色列表对象,角色内部包含权限对象,如下所示
@Document
@Data
public class User implements Serializable{
private String passwordResetToken;
private boolean enabled = false;
@DBRef(lazy= true)
private List<Role> roleList;
}
我的角色DTO如下
@Data
@Document
public class Role implements Serializable{
private String roleName;
private String description;
@DBRef(lazy= true)
private List<Permission> permissions;
}
现在在我的 spring MVC 中加载所有角色时我调用所有权限,因为这是重复操作我想缓存结果并使用 redis 并在加载角色值时收到以下异常。
raised java.lang.ClassCastException: com.learning.securedapp.domain.Permission cannot be cast to com.learning.securedapp.domain.Permission
帮我克服这个错误。
我附上 source code to my project and I receive error at line 91 of RoleController.java
要在您的本地环境中复制登录到应用程序并单击权限菜单,然后单击角色菜单,现在在角色菜单中单击任何编辑 icon.you 将收到上述错误。
当你使用带缓存的 DevTools 时,你需要注意 this limitation。
当对象被序列化到缓存中时,应用class加载器是C1。然后在你更改一些 code/configuration 之后,devtools 会自动重新启动上下文并创建一个新的 classloader (C2)。当您点击该缓存方法时,缓存抽象会在缓存中找到一个条目,并将其从存储中反序列化。如果缓存库不考虑上下文 classloader,该对象将附加错误的 classloader(这解释了奇怪的异常 A cannot be cast to A
)。
TL;DR
如果缓存库不使用上下文 classloader,请不要使用 devtools 序列化 classes。或者把你的缓存库 in the application classloader:
restart.include.yourcache=/my-cache-lib-[\w-]+\.jar
我实际上尝试了建议的解决方案(及其许多变体),但没有成功。例如,这并没有阻止问题的发生:
restart.include.cache=/spring-data-redis-.*.jar
我更新了上面的内容以标注我正在使用的特定版本,但它仍然不起作用。
我最终所做的工作是从我的项目中排除 spring-boot-devtools。我正在使用 Maven,所以注释是这样的:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<version>[1.5.9,)</version>
<scope>provided</scope>
</dependency>
这将阻止任何等于或大于 1.5.9 的版本加载。在我包含上述内容之后,一切都按预期进行。我知道这不是一个理想的解决方案,但我很少使用 devtools 的重启功能,所以这对我来说实际上是一个很好的方法。
我正在使用 Spring Boot 2.0.5,最后我从 pom.xml 中完全删除了 devtools。感谢@Always Learning 的上述回答。
尽管我很讨厌这样做,但我现在找不到其他方法!
<!--
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
-->
这对我有用,DevTools 和 Redis 都可以。我们需要在创建 JdkSerializationRedisSerializer 时传递 classLoader,它应该可以工作
JdkSerializationRedisSerializer redisSerializer = new JdkSerializationRedisSerializer(getClass().getClassLoader());
所以我的 RedisCacheConfig 是:
@Configuration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport implements CachingConfigurer {
............................
............................
@Bean
public RedisCacheManager redisCacheManager(LettuceConnectionFactory lettuceConnectionFactory) {
JdkSerializationRedisSerializer redisSerializer = new JdkSerializationRedisSerializer(getClass().getClassLoader());
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.disableCachingNullValues()
.entryTtl(Duration.ofHours(redisDataTTL))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer));
redisCacheConfiguration.usePrefix();
RedisCacheManager redisCacheManager = RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(lettuceConnectionFactory)
.cacheDefaults(redisCacheConfiguration)
.build();
redisCacheManager.setTransactionAware(true);
return redisCacheManager;
}
............................
............................
}
检查此 spring 引导问题:https://github.com/spring-projects/spring-boot/issues/9444
我的应用程序在 Spring Boot 1.4.0M3 上运行时遇到一个奇怪的问题,它使用 Spring 缓存实现,其中提供程序是 Redis,我收到 classCastException 无法转换相同的对象
我正在使用 Mongodb 作为数据库,我有用户对象,其中包含延迟加载的角色列表对象,角色内部包含权限对象,如下所示
@Document
@Data
public class User implements Serializable{
private String passwordResetToken;
private boolean enabled = false;
@DBRef(lazy= true)
private List<Role> roleList;
}
我的角色DTO如下
@Data
@Document
public class Role implements Serializable{
private String roleName;
private String description;
@DBRef(lazy= true)
private List<Permission> permissions;
}
现在在我的 spring MVC 中加载所有角色时我调用所有权限,因为这是重复操作我想缓存结果并使用 redis 并在加载角色值时收到以下异常。
raised java.lang.ClassCastException: com.learning.securedapp.domain.Permission cannot be cast to com.learning.securedapp.domain.Permission
帮我克服这个错误。
我附上 source code to my project and I receive error at line 91 of RoleController.java
要在您的本地环境中复制登录到应用程序并单击权限菜单,然后单击角色菜单,现在在角色菜单中单击任何编辑 icon.you 将收到上述错误。
当你使用带缓存的 DevTools 时,你需要注意 this limitation。
当对象被序列化到缓存中时,应用class加载器是C1。然后在你更改一些 code/configuration 之后,devtools 会自动重新启动上下文并创建一个新的 classloader (C2)。当您点击该缓存方法时,缓存抽象会在缓存中找到一个条目,并将其从存储中反序列化。如果缓存库不考虑上下文 classloader,该对象将附加错误的 classloader(这解释了奇怪的异常 A cannot be cast to A
)。
TL;DR
如果缓存库不使用上下文 classloader,请不要使用 devtools 序列化 classes。或者把你的缓存库 in the application classloader:
restart.include.yourcache=/my-cache-lib-[\w-]+\.jar
我实际上尝试了建议的解决方案(及其许多变体),但没有成功。例如,这并没有阻止问题的发生:
restart.include.cache=/spring-data-redis-.*.jar
我更新了上面的内容以标注我正在使用的特定版本,但它仍然不起作用。
我最终所做的工作是从我的项目中排除 spring-boot-devtools。我正在使用 Maven,所以注释是这样的:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<version>[1.5.9,)</version>
<scope>provided</scope>
</dependency>
这将阻止任何等于或大于 1.5.9 的版本加载。在我包含上述内容之后,一切都按预期进行。我知道这不是一个理想的解决方案,但我很少使用 devtools 的重启功能,所以这对我来说实际上是一个很好的方法。
我正在使用 Spring Boot 2.0.5,最后我从 pom.xml 中完全删除了 devtools。感谢@Always Learning 的上述回答。
尽管我很讨厌这样做,但我现在找不到其他方法!
<!--
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
-->
这对我有用,DevTools 和 Redis 都可以。我们需要在创建 JdkSerializationRedisSerializer 时传递 classLoader,它应该可以工作
JdkSerializationRedisSerializer redisSerializer = new JdkSerializationRedisSerializer(getClass().getClassLoader());
所以我的 RedisCacheConfig 是:
@Configuration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport implements CachingConfigurer {
............................
............................
@Bean
public RedisCacheManager redisCacheManager(LettuceConnectionFactory lettuceConnectionFactory) {
JdkSerializationRedisSerializer redisSerializer = new JdkSerializationRedisSerializer(getClass().getClassLoader());
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.disableCachingNullValues()
.entryTtl(Duration.ofHours(redisDataTTL))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer));
redisCacheConfiguration.usePrefix();
RedisCacheManager redisCacheManager = RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(lettuceConnectionFactory)
.cacheDefaults(redisCacheConfiguration)
.build();
redisCacheManager.setTransactionAware(true);
return redisCacheManager;
}
............................
............................
}
检查此 spring 引导问题:https://github.com/spring-projects/spring-boot/issues/9444