Spring Session基于Redis存储的序列化问题 您所在的位置:网站首页 springbootredis序列化 Spring Session基于Redis存储的序列化问题

Spring Session基于Redis存储的序列化问题

2023-04-04 00:35| 来源: 网络整理| 查看: 265

  Spring redis SESSION 是如何进行反序列化?

  Spring session针对Web的Request请求有一个org.springframework.session.web.http.SessionRepositoryFilter过滤器,根据SESSION ID获取相应的SESSION对象。

@Order(SessionRepositoryFilter.DEFAULT_ORDER) public class SessionRepositoryFilter extends OncePerRequestFilter{ ... private final SessionRepository sessionRepository; ... }

  SessionRepositoryFilter会调用sessionRepository.findById(sessionId)来查找SESSION对象,对于Redis,sessionRepository实现类为org.springframework.session.data.redis.RedisOperationsSessionRepository,该类默认的序列化类为org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.   

public class RedisOperationsSessionRepository implements FindByIndexNameSessionRepository, MessageListener { ... private RedisSerializer defaultSerializer = new JdkSerializationRedisSerializer(); ... }

  查询JdkSerializationRedisSerializer源码,发现该类在反序列化时如果异常会抛出SerializationException异常,而SessionRepositoryFilter又没有处理异常,故如果序列化异常时就会导致请求异常。

public class JdkSerializationRedisSerializer implements RedisSerializer { private final Converter serializer; private final Converter deserializer; /** * Creates a new {@link JdkSerializationRedisSerializer} using the default class loader. */ public JdkSerializationRedisSerializer() { this(new SerializingConverter(), new DeserializingConverter()); } /** * Creates a new {@link JdkSerializationRedisSerializer} using a {@link ClassLoader}. * * @param classLoader * @since 1.7 */ public JdkSerializationRedisSerializer(ClassLoader classLoader) { this(new SerializingConverter(), new DeserializingConverter(classLoader)); } /** * Creates a new {@link JdkSerializationRedisSerializer} using a {@link Converter converters} to serialize and * deserialize objects. * * @param serializer must not be {@literal null} * @param deserializer must not be {@literal null} * @since 1.7 */ public JdkSerializationRedisSerializer(Converter serializer, Converter deserializer) { Assert.notNull(serializer, "Serializer must not be null!"); Assert.notNull(deserializer, "Deserializer must not be null!"); this.serializer = serializer; this.deserializer = deserializer; } public Object deserialize(@Nullable byte[] bytes) { if (SerializationUtils.isEmpty(bytes)) { return null; } try { return deserializer.convert(bytes); } catch (Exception ex) { throw new SerializationException("Cannot deserialize", ex); } } @Override public byte[] serialize(@Nullable Object object) { if (object == null) { return SerializationUtils.EMPTY_ARRAY; } try { return serializer.convert(object); } catch (Exception ex) { throw new SerializationException("Cannot serialize", ex); } } }

  如何解决这个异常呢?定制Spring redis session的序列化类,替代原有的默认的JdkSerializationRedisSerializer。

@Configuration @EnableRedisHttpSession(maxInactiveIntervalInSeconds = 86400) public class RedisConfig { @Bean public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate redisTemplate = new RedisTemplate(); FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class); redisTemplate.setValueSerializer(fastJsonRedisSerializer); redisTemplate.setHashValueSerializer(fastJsonRedisSerializer); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setConnectionFactory(redisConnectionFactory); redisTemplate.setDefaultSerializer(new StringRedisSerializer()); redisTemplate.afterPropertiesSet(); return redisTemplate; } @Bean RedisSerializer springSessionDefaultRedisSerializer() { return new GenericFastJsonRedisSerializer(); } }

  在原有序列化JdkSerializationRedisSerializer对象的基础上,在反序列化异常时捕获这个异常,仅记录相关日志即可

@Component("springSessionDefaultRedisSerializer") public class CustomSessionDefaultRedisSerializer extends JdkSerializationRedisSerializer { private static final Logger LOG = LoggerFactory.getLogger(CustomSessionDefaultRedisSerializer.class); public Object deserialize(@Nullable byte[] bytes) { Object deserialObj = null; try { deserialObj = super.deserialize(bytes); } catch(Exception e) { LOG.warn("deserialize session Object error!", e); } return deserialObj; } }

参考:

       https://blog.yl-online.top/posts/74b23c9e.html

   

  



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有