Session 是伺服器為每個客戶端瀏覽器創建的會話上下文,生命週期默認 30 分鐘無活動後失效。本質是伺服器內存中的一個 Map,鍵為屬性名,值為任意對象。
JSESSIONID (UUID)JSP 頁面無需聲明,直接使用 session 變量 (類型 HttpSession)。
| 操作 | 方法 | 示例 |
|---|---|---|
| 存入屬性 | setAttribute(String name, Object value) | session.setAttribute("user", userObj); |
| 讀取屬性 | getAttribute(String name) | User u = (User) session.getAttribute("user"); |
| 移除屬性 | removeAttribute(String name) | session.removeAttribute("cart"); |
| 獲取所有屬性名 | getAttributeNames() | Enumeration |
| 獲取 Session ID | getId() | String id = session.getId(); |
| 創建時間 | getCreationTime() | long t = session.getCreationTime(); |
| 最後訪問時間 | getLastAccessedTime() | long t = session.getLastAccessedTime(); |
| 設置失效時間(秒) | setMaxInactiveInterval(int seconds) | session.setMaxInactiveInterval(30*60); // 30分 |
| 獲取失效時間(秒) | getMaxInactiveInterval() | int sec = session.getMaxInactiveInterval(); |
| 強制失效 | invalidate() | session.invalidate(); // 登出調用 |
| 是否新會話 | isNew() | if (session.isNew()) ... |
<%-- login.jsp 驗證成功後 --%>
<%
User user = userService.authenticate(username, password);
if (user != null) {
session.setAttribute("loginUser", user); // 存入用戶對象
response.sendRedirect("index.jsp");
} else {
out.println("用戶名或密碼錯誤");
}
%>
<%-- 每個受保護頁面頂部 --%>
<%
User user = (User) session.getAttribute("loginUser");
if (user == null) {
response.sendRedirect("login.jsp?redirect=" + URLEncoder.encode(request.getRequestURI(), "UTF-8"));
return; // 停止執行後續頁面
}
// 可選:角色權限檢查
if (!user.hasRole("ADMIN") && request.getRequestURI().contains("/admin/")) {
response.sendError(403, "權限不足");
return;
}
%>
<%-- 添加商品到購物車 --%>
<%
List cart = (List) session.getAttribute("cart");
if (cart == null) {
cart = new ArrayList<>();
session.setAttribute("cart", cart);
}
// 添加或更新商品邏輯
cart.add(new CartItem(productId, quantity));
%>
方式一:web.xml (全局)
<session-config>
<session-timeout>60</session-timeout> <!-- 分鐘 -->
</session-config>
方式二:代碼動態設置 (單個會話)
session.setMaxInactiveInterval(60 * 60); // 1 小時,單位秒
| 方案 | 原理 | 適用場景 |
|---|---|---|
| Sticky Session (IP Hash) | 負載均衡器固定用戶到同一節點 | 簡單、小集群、可容忍單點故障 |
| Session 複製 (Tomcat DeltaManager) | 節點間廣播同步 Session 變更 | 小集群(<8節點)、低寫入量 |
| Redis 共享 Session (Spring Session) | Session 序列化存 Redis,所有節點讀寫 | 大型集群、微服務、高可用 |
| 資料庫持久化 | 定時/異步寫入 DB | 需長期保留、審計合規 |
removeAttribute() 或 invalidate()
// 獲取現有或創建新
HttpSession session = request.getSession(true); // 等同 request.getSession()
// 僅獲取現有,不創建
HttpSession session = request.getSession(false);
if (session != null) {
// 已有會話
}
Secure (僅 HTTPS)、HttpOnly (防 XSS)、SameSite=Strict/Lax (防 CSRF)session.invalidate() 再 request.getSession(true) 防固定攻擊session.isNew() || session.getAttribute("user")==null| 現象 | 可能原因 | 排查方向 |
|---|---|---|
| Session 丟失/頻繁重建 | 瀏覽器禁用 Cookie、URL 重寫失效 | 檢查 Cookie 設置、啟用 URL 重寫 response.encodeURL() |
| 集群環境 Session 不同步 | Sticky Session 失效、複製延遲 | 遷移至 Redis 共享 Session |
| 內存溢出 (OOM) | Session 存放大對象、未清理、超時過長 | Heap Dump 分析、縮短超時、定時清理 |
| 並發修改異常 | 多線程同時操作同一 Session | Session 非線程安全,加同步鎖或用 ConcurrentHashMap 替代 |