Redis反序列化报错

1,076 阅读2分钟

背景

这个错误是这样的,我在项目中同时使用了spring-session和redis,并且对二者进行了相应的配置。 其中spring-session的配置如下:

@EnableRedisHttpSession
@Configuration
public class SessionConfig {

// cookie的序列化方式
   @Bean
   public CookieSerializer cookieSerializer() {
       DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
       cookieSerializer.setCookieName("XINYOUMALL-SESSION");
       cookieSerializer.setDomainName("xinyoumall.com");
       return cookieSerializer;
   }
//   redis的序列化方式
   @Bean
   public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
       return new GenericJackson2JsonRedisSerializer();
   }
}

在项目引入redis的时候,我也对redis进行了相关的配置。

@EnableCaching
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer(om);
        template.setConnectionFactory(factory);
        //key序列化方式
        template.setKeySerializer(jackson2JsonRedisSerializer);
        //value序列化
        template.setValueSerializer(jackson2JsonRedisSerializer);
        //value hashmap序列化
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.setHashKeySerializer(jackson2JsonRedisSerializer);
        return template;
    }

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();

        //解决查询缓存转换异常的问题
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.setDefaultTyping(new StdTypeResolverBuilder());
        GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer(om);
        // 配置序列化(解决乱码的问题),过期时间600秒
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(600))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
                .disableCachingNullValues();
        RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .build();
        return cacheManager;
    }

}

结果就是我的用户登录信息在session中创建以后,无法取出来,到达另外一个界面后将会报错。

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 java.io.StreamCorruptedException: invalid stream header: 31363430
	org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.deserialize(JdkSerializationRedisSerializer.java:84)
	org.springframework.data.redis.core.AbstractOperations.deserializeHashValue(AbstractOperations.java:355)
	org.springframework.data.redis.core.AbstractOperations.deserializeHashMap(AbstractOperations.java:299)
	org.springframework.data.redis.core.DefaultHashOperations.entries(DefaultHashOperations.java:247)
	org.springframework.data.redis.core.DefaultBoundHashOperations.entries(DefaultBoundHashOperations.java:183)
	org.springframework.session.data.redis.RedisIndexedSessionRepository.getSession(RedisIndexedSessionRepository.java:457)
	org.springframework.session.data.redis.RedisIndexedSessionRepository.findById(RedisIndexedSessionRepository.java:429)
	org.springframework.session.data.redis.RedisIndexedSessionRepository.findById(RedisIndexedSessionRepository.java:251)
	org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.getRequestedSession(SessionRepositoryFilter.java:356)
	org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.getSession(SessionRepositoryFilter.java:290)
	org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.getSession(SessionRepositoryFilter.java:193)
	org.springframework.web.util.WebUtils.getSessionId(WebUtils.java:359)
	org.springframework.web.servlet.FrameworkServlet.publishRequestHandledEvent(FrameworkServlet.java:1145)
	org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1023)
	org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:655)
	org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
	org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
	org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
	org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
	org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:142)
	org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:82)
	org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
	org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)

不难看出,就是说我们的反序列化异常。
刚开始感觉到跟奇怪,因为我是先引入了redis,并且进行了使用,并没有出现任何的问题。但是在引入spring-session后出现了这个异常。

然后自己就进行了各种骚操作。包括修改redis配置文件的序列化方式。 删除redis的配置文件,使用spring-session的配置文件等等。【因为该过程是跟从着尚硅谷老师在做的一个项目,spring-session的配置文件完全相同,但是redis的配置文件不同。所有我就确信是redis配置文件出现了错误】

解决

瞎操作了很久,最后把spring-session中关于redis序列化的配置删除了,项目恢复了正常。删除后的spring-session配置文件如下:

@EnableRedisHttpSession
@Configuration
public class SessionConfig {

// cookie的序列化方式
    @Bean
    public CookieSerializer cookieSerializer() {
        DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
        cookieSerializer.setCookieName("XINYOUMALL-SESSION");
        cookieSerializer.setDomainName("xinyoumall.com");
        return cookieSerializer;
    }
    
}

为什么删除一个配置就好了?

因为我在redis和spring-session的两个配置文件中都配置了redis的序列化方式呀!!发生了冲突,太马虎了。 在此留下纪念。