java.lang.ClassCastException:DTOObject无法强制转换为DTOObject

raj*_*lli 4 spring caching spring-mvc redis-cache spring-boot

我在我的应用程序中面临一个奇怪的问题,它运行在Spring Boot 1.4.0M3上,它使用Spring缓存实现,其中provider是Redis,我收到classCastException,相同的对象无法生成

我使用Mongodb作为数据库,我有User Object,其中包含懒惰加载的Roles对象列表,Roles内部包含权限对象,如下所示

@Document
@Data
public class User implements Serializable{
private String passwordResetToken;

private boolean enabled = false;

@DBRef(lazy= true)
private List<Role> roleList;
}
Run Code Online (Sandbox Code Playgroud)

我的角色DTO如下

@Data
@Document
public class Role implements Serializable{
   private String roleName;
    private String description;
    @DBRef(lazy= true)
    private List<Permission> permissions;
}
Run Code Online (Sandbox Code Playgroud)

现在在我的Spring MVC加载所有角色时我调用所有权限,因为这是重复操作,我想到缓存结果并使用redis,同时加载我在异常下面收到的角色值.

raised java.lang.ClassCastException: com.learning.securedapp.domain.Permission cannot be cast to com.learning.securedapp.domain.Permission
Run Code Online (Sandbox Code Playgroud)

帮助我克服这个错误.

我将源代码附加到我的项目,并在RoleController.java的第91行收到错误

要在本地环境中复制,请登录到应用程序,然后单击权限菜单,然后单击角色菜单,在角色菜单中,现在单击任何编辑图标.您将收到以上错误.

Muk*_*h M 10

这对我有用,DevTools 和 Redis 都可以工作。我们在创建JdkSerializationRedisSerializer时需要传递classLoader,它应该可以工作

 JdkSerializationRedisSerializer redisSerializer = new JdkSerializationRedisSerializer(getClass().getClassLoader());
Run Code Online (Sandbox Code Playgroud)

所以我的 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;
}

............................
............................


}
Run Code Online (Sandbox Code Playgroud)

检查这个 Spring Boot 问题:https://github.com/spring-projects/spring-boot/issues/9444


Ste*_*oll 7

当您使用DevTools进行缓存时,您需要了解此限制.

当对象序列化到缓存中时,应用程序类加载器为C1.然后在更改某些代码/配置后,devtools会自动重新启动上下文并创建一个新的类加载器(C2).当您点击该缓存方法时,缓存抽象会在缓存中找到一个条目,并将其从商店反序列化.如果缓存库没有考虑上下文类加载器,那么该对象将附加错误的类加载器(这解释了奇怪的异常A cannot be cast to A).

TL;DR如果缓存库不使用上下文类加载器,请不要使用devtools序列化类.或者将缓存库放在应用程序类加载器中:

restart.include.yourcache=/my-cache-lib-[\\w-]+\.jar
Run Code Online (Sandbox Code Playgroud)