【问题标题】:Error accessing Spring session data stored in Redis访问存储在 Redis 中的 Spring 会话数据时出错
【发布时间】:2026-01-09 21:00:01
【问题描述】:

在我的 REST 控制器 Spring 项目中,我想将 Session 信息存储在 Redis 中。

在我的 application.properties 我定义了以下内容:

spring.session.store-type=redis
spring.session.redis.namespace=rdrestcore

com.xyz.redis.host=192.168.201.46
com.xyz.redis.db=0
com.xyz.redis.port=6379
com.xyz.redis.pool.min-idle=5

我还启用了 Http Redis 会话:

@Configuration
@EnableRedisHttpSession 
public class SessionConfig extends AbstractHttpSessionApplicationInitializer 
{}

我终于有了这样的redis连接工厂:

@Configuration
@EnableRedisRepositories
public class RdRedisConnectionFactory {
    @Autowired 
    private Environment env;
    @Value("${com.xyz.redis.host}")
    private String redisHost;
    @Value("${com.xyz.redis.db}")
    private Integer redisDb;
    @Value("${com.xyz.redis.port}")
    private Integer redisPort;
    @Value("${com.xyz.redis.pool.min-idle}")
    private Integer redisPoolMinIdle;

    @Bean
    JedisPoolConfig jedisPoolConfig() {
        JedisPoolConfig poolConfig = new JedisPoolConfig();        
        if(redisPoolMinIdle!=null) poolConfig.setMinIdle(redisPoolMinIdle);

        return poolConfig;
    }

    @Bean    
    JedisConnectionFactory jedisConnectionFactory() {
        JedisConnectionFactory jedisConFactory = new JedisConnectionFactory();
        if(redisHost!=null) jedisConFactory.setHostName(redisHost);
        if(redisPort!=null) jedisConFactory.setPort(redisPort);
        if(redisDb!=null) jedisConFactory.setDatabase(redisDb);
        jedisConFactory.setPoolConfig(jedisPoolConfig());
        return jedisConFactory;
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        final RedisTemplate< String, Object > template =  new RedisTemplate();
        template.setConnectionFactory( jedisConnectionFactorySpring());
        template.setKeySerializer( new StringRedisSerializer() );
        template.setValueSerializer( new GenericJackson2JsonRedisSerializer() );
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer( new GenericJackson2JsonRedisSerializer() );

        return template;
    }
}

通过这种配置,会话信息被存储在 Redis 中,但是,它的序列化非常奇怪。我的意思是,键是可读的,但存储的值不是(我从一个名为“Redis Desktop Manager”的程序中查询信息)......例如......对于一个新会话,我得到一个带有键的哈希:

*spring:session:sessions:c1110241-0aed-4d40-9861-43553b3526cb*

这个哈希包含的键是:maxInactiveInterval、lastAccessedTime、creationTime、sessionAttr:SPRING_SECURITY_CONTEXT 但他们的值都是他们编码的类似于这样的东西:

\xAC\xED\x00\x05sr\x00\x0Ejava.lang.Long;\x8B\xE4\x90\xCC\x8F#\xDF\x02\x00\x01J\x00\x05valuexr\x00\x10java.lang。编号\x86\xAC\x95\x1D\x0B\x94\xE0\x8B\x02\x00\x00xp\x00\x00\x01b$G\x88*

(用于创建时间键)

如果我尝试使用 redisTemplate 从代码中访问此信息,它会引发如下异常:

目标虚拟机发生异常:无法反序列化;嵌套异常是 org.springframework.core.serializer.support.SerializationFailedException: 无法反序列化有效负载。字节数组是 DefaultDeserializer 的对应序列化?;嵌套异常 是 java.io.StreamCorruptedException:无效的流标头:73657373 org.springframework.data.redis.serializer.SerializationException:无法反序列化;嵌套异常是 org.springframework.core.serializer.support.SerializationFailedException: 无法反序列化有效负载。字节数组是 DefaultDeserializer 的对应序列化?;嵌套异常 是 java.io.StreamCorruptedException:无效的流标头:73657373 在 org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.deserialize(JdkSerializationRedisSerializer.java:82)

我认为这是 Spring 会话信息的序列化/反序列化的某种问题,但我不知道还能做些什么来控制它。

有谁知道我做错了什么?

谢谢

【问题讨论】:

  • 问题解决了吗?
  • 不,我终于停止尝试访问 Spring 存储的会话信息

标签: spring rest session redis spring-data-redis


【解决方案1】:

你在正确的轨道上,你的问题确实是序列化。试试这个配置(只用这些序列化器配置你的模板):

template.setHashValueSerializer(new JdkSerializationRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setKeySerializer(new StringRedisSerializer());
template.setDefaultSerializer(new JdkSerializationRedisSerializer());

【讨论】: