背景
这个错误是这样的,我在项目中同时使用了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的序列化方式呀!!发生了冲突,太马虎了。 在此留下纪念。