java Spring会话Redis无法反序列化,出现ClassNotFoundException异常

kjthegm6  于 2023-01-19  发布在  Java
关注(0)|答案(5)|浏览(473)
org.springframework.data.redis.serializer.SerializationException: Cannot deserialize; 
  nested exception is org.springframework.core.serializer.support.SerializationFailedException:

Failed to deserialize payload. Is the byte array a result of corresponding serialization for DefaultDeserializer?; 
  nested exception is org.springframework.core.NestedIOException:

Failed to deserialize object type; 
  nested exception is java.lang.ClassNotFoundException: com.foo.user.model.CurrentUser

我有两个典型的Spring Boot应用程序,它们共享一个Redis示例来显示会话状态。当尝试登录我的应用程序时,上面的错误立即发生。
我不太清楚这是怎么回事--两个应用程序都使用相同的库和版本来支持适用的用户模型和Spring依赖项。值得一提的是,CurrentUser扩展了org.springframework.security.core.userdetails.User,而org.springframework.security.core.userdetails.User本身就是Serializable
我重新启动了我的Redis示例,以为有什么东西变怪了,但事实并非如此。我想展示一下我已经尝试过的,但主要是确保我的工件被正确构建,并重新启动应用程序和Redis服务器,还有一点摆弄Serializable
为什么我会看到这个?

6xfqseft

6xfqseft1#

当发送方服务器与接收方服务器不同时(单独的服务器),您很可能会收到此错误
问题来自ValueSerializer
若要避免此问题,请使用Jackson2JsonRedisSerializer作为发送方和接收方的值Serializer

@Bean
    protected RedisTemplate<String, Object> redisTemplate() {
      final RedisTemplate<String, Object> template = new RedisTemplate<>();
      template.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
      .........
      return template;
    }

这样,序列化过程将基于JSON而不是基于类

q3qa4bjr

q3qa4bjr2#

异常显示“无法反序列化”看起来您在Redis中存储了一些内容,现在无法反序列化。您是否同时更改了serialVersionUID?
我看到你重新启动了Redis,但可能是条目被保留并在重新启动后幸存下来?

eimct9ow

eimct9ow3#

当你把数据存储到redis的时候,就把它类型转换成Object类,当你从redis取回数据的时候,就把它类型转换成Object类,然后把它类型转换成你拥有的任何POJO类,这在我的例子中是有效的,当存储-〉

redisTemplate.opsForHash().put("<YOUR-key>", "<YOUR-field>",(Object) empList);

提取时-〉

Object employeeFromCache=operation.get("<YOUR-key>", "<YOUR-field>");
        employees=(List<Employee>)employeeFromCache;
2j4z5cfb

2j4z5cfb4#

我也在做同样的事情。把数据存储到Redis的一个服务中,然后从另一个服务中获取。我也遇到了同样的问题(反序列化)。我制作了一个包含“Serializable”类的公共库。两个服务使用了相同的库。这对我很有效。如果这个实现有任何问题,请告诉我。谢谢

noj0wjuj

noj0wjuj5#

Redis中valueSerializer的默认 Spring Boot 配置是JdkSerializationRedisSerializer
所以当你改变之前在Redis中缓存的对象时,你也必须从Redis中删除它。
最后,你需要在应用程序启动时删除Redis键值,如下所示:

@Component
public class RemoveCachesOnStartup {
  private final RedisTemplate<Object, Object> redisTemplate;

  @PostConstruct
  public void doAfterStartup() {
    redisTemplate.setKeySerializer(new StringRedisSerializer());
    int count = 0;
    Set<Object> keys = redisTemplate.keys("*");
    if (keys != null) {
      for (Object key : keys) {
        if (key.toString().startsWith(CACHE_PREFIX)) {
          redisTemplate.delete(key);
          count++;
        }
      }
    }
    log.info("total {} data redis records have executed", count);
  }

相关问题