首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Session 數據莫名消失卻未過期?根因分析與 Serializable 解決方案實戰

     編輯:Java 綜合教學

Session 數據莫名消失卻未過期?根因分析與 Serializable 解決方案實戰

常見場景:登錄用戶資訊存入 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());
    }
}

關鍵觀察現象

  • 訪問 Servlet 存入 User 物件與 String 訊息後重定向顯示正常
  • 約 54 秒後,控制台輸出:「移除屬性:user」,但 message 未移除,**Session 未銷毀**
  • 刷新頁面顯示用戶名消失,僅剩字符串訊息

根因深度分析

Tomcat 在 Session 被動複製、叢集同步或內存壓力下進行序列化/反序列化時,若物件未實現 java.io.Serializable,容器可能靜默丟棄該屬性而不拋出異常。字符串、基本類型包裝類預設可序列化,自定義 POJO 必須顯式實現。

解決方案:實現 Serializable 介面

public class User implements Serializable {
    private static final long serialVersionUID = 1L; // 建議顯式聲明
    private int id;
    private String name;
    // getter/setter...
}

驗證結果

  • 修改後重新部署,Session 中的 User 物件不再意外消失
  • 除非 Session 真正過期或手動 invalidate(),數據持久保留

延伸知識:序列化機制

物件序列化將實現 Serializable 的物件轉為位元組序列,可持久化存儲或網路傳輸。反序列化時依據 serialVersionUID 驗證版本一致性,重建物件狀態。Socket 傳輸物件、Session 叢集同步、分布式緩存(Redis/Memcached)均依賴此機制。

避坑指南

  1. 所有存入 Session 的自定義物件**必須實現 Serializable**
  2. 靜態變量、transient 修飾字段不參與序列化
  3. 叢集環境下確保所有節點類路徑一致,serialVersionUID 固定
  4. 大物件慎存 Session,建議改用 Redis 等外部存儲
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved