Spring Boot 3.2能否控制重置会话非活动状态的请求范围?
实现方案:控制Spring Boot 3.2应用中会话非活动状态的重置逻辑
完全可以实现页面请求重置会话非活动状态、API请求不重置的需求,核心是通过自定义Servlet过滤器干预会话的lastAccessedTime更新逻辑,避免轮询API导致会话永不超时。以下是具体实现步骤:
核心思路
Servlet规范中,默认每次请求访问HttpSession时会自动更新lastAccessedTime(即重置会话非活动状态)。我们需要针对API请求,在请求处理前后保存并恢复原始的lastAccessedTime,从而跳过重置操作;页面请求则保留默认逻辑。
自定义过滤器实现
创建一个优先级高于Spring默认会话管理过滤器的自定义过滤器,代码示例如下:
import jakarta.servlet.*; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpSession; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import java.io.IOException; @Component @Order(Ordered.HIGHEST_PRECEDENCE + 10) // 确保在Spring SessionManagementFilter之前执行 public class SessionAccessControlFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; String requestURI = httpRequest.getRequestURI(); // 根据实际项目调整API请求的匹配规则,比如前缀、请求头等 boolean isApiRequest = requestURI.startsWith("/api/"); if (isApiRequest) { // 获取已存在的会话(不创建新会话) HttpSession session = httpRequest.getSession(false); Long originalLastAccessedTime = null; if (session != null) { // 保存会话原始的非活动时间戳 originalLastAccessedTime = session.getLastAccessedTime(); } // 继续执行后续请求逻辑 chain.doFilter(request, response); // 恢复会话的原始非活动时间,跳过重置 if (session != null && originalLastAccessedTime != null) { session.setLastAccessedTime(originalLastAccessedTime); } } else { // 页面请求直接放行,保留默认的会话重置逻辑 chain.doFilter(request, response); } } }
关键注意事项
- 请求匹配规则:根据项目实际情况调整API请求的判断逻辑,比如通过请求路径前缀(如
/api/)、请求Content-Type(如application/json)或自定义请求头区分API与页面请求。 - 过滤器优先级:通过
@Order确保自定义过滤器在Spring的SessionManagementFilter之前执行(SessionManagementFilter默认优先级为-100,设置更高优先级的数值即可)。 - 会话依赖场景:如果API请求需要使用会话,上述方案可以正常兼容;若API完全不需要会话,可直接在过滤器中返回
null作为会话对象,进一步简化逻辑。 - 部署兼容性:该方案在独立WAR包部署与内嵌容器部署的Spring Boot应用中均有效,因为本质是基于Servlet规范的过滤器逻辑。
验证方式
- 发起页面请求后,查看会话的
lastAccessedTime是否更新为当前时间。 - 多次发起API请求后,确认会话的
lastAccessedTime仍保持页面请求后的时间,会话会按配置的超时时间正常过期。
内容的提问来源于stack exchange,提问作者E-Riz
相关产品推荐
相关产品推荐

