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

SpringBoot Mongo HttpSession:如何结合SpringHttpSessionConfiguration自定义SessionRepositoryFilter?

解决Spring Boot Mongo会话频繁持久化问题:仅每隔5分钟保存一次访问记录

1. 自定义SessionRepositoryFilter,添加时间判断逻辑

继承SessionRepositoryFilter,重写核心方法,在会话提交前判断距离上次持久化是否超过5分钟,仅满足条件时才执行Mongo写入操作:

import org.springframework.session.Session;
import org.springframework.session.SessionRepository;
import org.springframework.session.web.http.SessionRepositoryFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.Duration;
import java.time.Instant;

public class LazySaveMongoSessionRepositoryFilter<S extends Session> extends SessionRepositoryFilter<S> {

    private static final Duration SAVE_INTERVAL = Duration.ofMinutes(5);

    public LazySaveMongoSessionRepositoryFilter(SessionRepository<S> sessionRepository) {
        super(sessionRepository);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        super.doFilterInternal(request, response, () -> {
            try {
                S session = getSession(request);
                if (session != null) {
                    Instant lastSaveTime = getLastSaveTime(session);
                    Instant now = Instant.now();
                    // 新会话或距离上次保存超过5分钟时,执行持久化
                    if (lastSaveTime == null || Duration.between(lastSaveTime, now).compareTo(SAVE_INTERVAL) > 0) {
                        session.setLastAccessedTime(now);
                        getSessionRepository().save(session);
                        session.setAttribute("LAST_SAVE_TIMESTAMP", now);
                    } else {
                        // 仅更新内存中的最后访问时间,不写入Mongo
                        session.setLastAccessedTime(now);
                    }
                }
                filterChain.doFilter(request, response);
            } catch (IOException | ServletException e) {
                throw new RuntimeException(e);
            }
        });
    }

    @SuppressWarnings("unchecked")
    private Instant getLastSaveTime(S session) {
        return (Instant) session.getAttribute("LAST_SAVE_TIMESTAMP");
    }
}

2. 覆盖SpringHttpSessionConfiguration的过滤器Bean

创建配置类继承SpringHttpSessionConfiguration,替换默认的过滤器为自定义实现:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.session.SessionRepository;
import org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration;

@Configuration
public class CustomHttpSessionConfiguration extends SpringHttpSessionConfiguration {

    @Override
    @Bean
    public <S extends org.springframework.session.Session> SessionRepositoryFilter<S> sessionRepositoryFilter(SessionRepository<S> sessionRepository) {
        return new LazySaveMongoSessionRepositoryFilter<>(sessionRepository);
    }
}

3. 关键说明

  • 会话的30分钟过期时间不受影响,Mongo的TTL索引会正常清理过期会话;
  • 若会话中有业务属性变更(如用户登录状态修改),需手动调用sessionRepository.save(session)确保变更及时持久化;
  • 新会话会立即执行第一次持久化,后续仅每隔5分钟触发一次写入操作。

内容的提问来源于stack exchange,提问作者SOUser2009 Geeky

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 11:09:16