You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法修改Redis中Spring Session的TTL值问题求助

Spring Session Redis键TTL无法修改的问题排查与解决

问题背景

自定义Redis键(如示例中的"2")的TTL设置正常,但无法修改Spring Session存储在Redis中的目标键(格式为RedisPrefixConstants.SPRING_SESSION_SESSIONS + httpSession.getId())的TTL,且已确认键名正确。相关代码如下:

@RequestMapping("/loginByEmail")
@GlobalInterceptor(checkParams = true)
public ResponseVO loginByEmail(HttpSession httpSession,
                        HttpServletRequest request,
                        @VerifyParam(required = true, param = "email") String email,
                        @VerifyParam(required = true, param = "password") String password,
                        @VerifyParam(required = true, param = "checkCode") String checkCode) {


    try {
        
//        if (!checkCode.equalsIgnoreCase((String) httpSession.getAttribute(CHECK_CODE_KEY))) {
//            throw new BusinessException("wrong code");
//        }

      
        String token = loginService.loginByEmail(email, password, getIpAddress(request));
        httpSession.setAttribute(Constants.SESSION_KEY, token);

        
        return getSuccessResponseVO(token);

    } finally {
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new StringRedisSerializer());
        redisTemplate.opsForValue().set("2","2");
        redisTemplate.expire("2", 1, TimeUnit.DAYS);
        System.out.println(RedisPrefixConstants.SPRING_SESSION_SESSIONS + httpSession.getId());
        httpSession.removeAttribute(CHECK_CODE_KEY);
    }

}

核心原因及对应解决方案

1. Spring Session自动TTL刷新覆盖手动设置

Spring Session默认会在每次请求处理完成后自动刷新Session的TTL,你手动调用expire()设置的过期时间会被Spring内置的Session保存逻辑覆盖。

解决方法:

  • 全局配置优先:直接通过配置文件设置Session默认超时时间,无需手动修改。Spring Boot示例:
    spring.session.timeout=86400 # 单位秒,此处设置为1天
    
  • 动态修改特定Session:通过Spring Session提供的RedisOperationsSessionRepository操作,避免被默认逻辑覆盖:
    @Autowired
    private RedisOperationsSessionRepository sessionRepository;
    
    // 在需要修改的位置执行
    Session targetSession = sessionRepository.findById(httpSession.getId());
    targetSession.setMaxInactiveInterval(Duration.ofDays(1));
    sessionRepository.save(targetSession);
    

2. RedisTemplate序列化器不统一

你在finally块中临时设置序列化器,但Spring Session自身使用的RedisTemplate实例可能和你代码中的redisTemplate不是同一个,导致实际操作的键与Spring Session存储的键存在序列化差异(表面键名一致,实际Redis中存储的键可能因序列化器不同而不匹配)。

解决方法:

  • 全局统一Redis序列化配置,在配置类中定义统一的RedisTemplate:
    @Configuration
    public class RedisConfig {
        @Bean
        public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
            RedisTemplate<String, Object> template = new RedisTemplate<>();
            template.setConnectionFactory(connectionFactory);
            StringRedisSerializer stringSerializer = new StringRedisSerializer();
            // 统一设置所有序列化器为StringRedisSerializer
            template.setKeySerializer(stringSerializer);
            template.setValueSerializer(stringSerializer);
            template.setHashKeySerializer(stringSerializer);
            template.setHashValueSerializer(stringSerializer);
            template.afterPropertiesSet();
            return template;
        }
    }
    

3. 执行顺序导致手动设置被覆盖

你的TTL修改操作在finally块中执行,而Spring Session的Session持久化操作可能在请求生命周期的更晚阶段(如拦截器后置处理、过滤器收尾)执行,导致手动设置的TTL被后续的Spring Session保存逻辑重置。

解决方法:

  • 监听Session创建事件,在Session完成持久化后修改TTL:
    @EventListener
    public void onSessionCreated(SessionCreatedEvent event) {
        String sessionId = event.getSession().getId();
        String redisKey = RedisPrefixConstants.SPRING_SESSION_SESSIONS + sessionId;
        redisTemplate.expire(redisKey, 1, TimeUnit.DAYS);
    }
    

内容的提问来源于stack exchange,提问作者Lee Anony

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 07:22:49