常見場景:登錄用戶資訊存入 Session,幾秒未操作刷新頁面,用戶名消失,但 Session 並未銷毀。調大 session-timeout、調整 Tomcat 配置均無效。本文透過監聽器追蹤定位根因,並給出徹底解決方案。
// Session 監聽器:監聽屬性增刪改
public class SessionListener implements HttpSessionListener, HttpSessionAttributeListener {
private long addTime;
@Override public void sessionCreated(HttpSessionEvent se) { System.out.println("Session 創建"); }
@Override public void sessionDestroyed(HttpSessionEvent se) { System.out.println("Session 銷毀"); }
@Override public void attributeAdded(HttpSessionBindingEvent se) {
System.out.println("添加屬性:" + se.getName());
addTime = System.currentTimeMillis();
}
@Override public void attributeRemoved(HttpSessionBindingEvent se) {
System.out.println("移除屬性:" + se.getName());
long t = (System.currentTimeMillis() - addTime) / 1000;
System.out.println("數據存活時間:" + t + "秒");
}
@Override public void attributeReplaced(HttpSessionBindingEvent se) {
System.out.println("更改屬性:" + se.getName());
}
}
User 物件與 String 訊息後重定向顯示正常message 未移除,**Session 未銷毀**Tomcat 在 Session 被動複製、叢集同步或內存壓力下進行序列化/反序列化時,若物件未實現 java.io.Serializable,容器可能靜默丟棄該屬性而不拋出異常。字符串、基本類型包裝類預設可序列化,自定義 POJO 必須顯式實現。
public class User implements Serializable {
private static final long serialVersionUID = 1L; // 建議顯式聲明
private int id;
private String name;
// getter/setter...
}
User 物件不再意外消失invalidate(),數據持久保留物件序列化將實現
Serializable的物件轉為位元組序列,可持久化存儲或網路傳輸。反序列化時依據serialVersionUID驗證版本一致性,重建物件狀態。Socket 傳輸物件、Session 叢集同步、分布式緩存(Redis/Memcached)均依賴此機制。
Serializable**transient 修飾字段不參與序列化serialVersionUID 固定