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
相关产品推荐
相关产品推荐

