Glassfish中自动页面重载致会话超时失效,如何区分用户活跃与自动操作?
区分主动操作/自动重载与追踪用户非活跃状态的方案
给自动重载请求打标记
在自动重载的JS逻辑里附加专属标识,后端通过这个标识区分请求类型:
- 前端实现:
若为页面重载,给URL加参数:
若为AJAX调用Servlet,加自定义请求头:// 自动重载函数 function autoReloadPage() { window.location = window.location.pathname + '?auto_reload=1'; }fetch('/your-servlet', { method: 'GET', headers: { 'X-Auto-Reload': '1' } }); - 后端判断:
Servlet中读取标识:
JSF中通过boolean isAutoReload = "1".equals(request.getParameter("auto_reload")) || "1".equals(request.getHeader("X-Auto-Reload"));ExternalContext获取:ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext(); boolean isAutoReload = "1".equals(ec.getRequestParameterMap().get("auto_reload"));
追踪用户真实活跃状态
通过记录最后主动操作时间,忽略自动重载带来的会话刷新:
- 前端监听主动交互:
全局监听用户点击、键盘输入等行为,记录并同步最后活跃时间:let lastActive = Date.now(); ['click', 'keydown', 'scroll'].forEach(evt => { document.addEventListener(evt, () => { lastActive = Date.now(); // 同步到后端 fetch('/sync-active-time', { method: 'POST', body: new URLSearchParams({ lastActive: lastActive }) }); }, { passive: true }); }); - 后端维护活跃时间:
在会话中存储真实活跃时间,自动重载时不更新,仅检查是否超时:HttpSession session = request.getSession(); boolean isAutoReload = /* 前面的判断逻辑 */; if (!isAutoReload) { // 主动操作,更新活跃时间 session.setAttribute("userLastActive", System.currentTimeMillis()); } else { // 自动重载,检查是否已超时 Long lastActive = (Long) session.getAttribute("userLastActive"); if (lastActive != null && (System.currentTimeMillis() - lastActive) > 30 * 60 * 1000) { session.invalidate(); response.sendRedirect("/login.xhtml"); } }
利用PrimeFaces IdleMonitor简化开发
PrimeFaces内置的IdleMonitor组件可直接追踪非活跃状态,无需手动写监听:
<p:idleMonitor timeout="#{30 * 60 * 1000}" onidle="triggerSessionTimeout()" /> <script> function triggerSessionTimeout() { // 非活跃超时后销毁会话 fetch('/destroy-session', { method: 'POST' }); } </script>
结合自动重载的标识判断,确保只有用户主动操作才续期会话。
内容的提问来源于stack exchange,提问作者Bohdan Myslyvchuk
相关产品推荐
相关产品推荐

