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

Java Web 專案用戶實體類最佳實踐:Session 儲存而非全域變數

     編輯:程式設計綜合問答

在 Java Web 專案中,用戶登入後的實體物件(如 User)應儲存在 HttpSession 中,而非定義為 Controller 的全域變數(類別層級欄位)。全域變數在多執行緒環境下會導致嚴重的線程安全問題與資料洩漏。

錯誤做法:Controller 全域變數

@Controller
public class UserController {
    private User currentUser; // 極度危險!所有請求共享同一實例
    
    @RequestMapping("/login")
    public String login(User user) {
        this.currentUser = userService.login(user); // 覆蓋其他用戶資料
        return "home";
    }
}

後果:Servlet 預設單例,多用戶並發登入時,currentUser 會被最後登入的用戶覆蓋,導致 A 用戶看到 B 用戶的資料。

正確做法:Session 儲存

@RequestMapping("/login")
public String login(User user, HttpSession session) {
    User dbUser = userService.login(user);
    if (dbUser != null) {
        session.setAttribute("currentUser", dbUser); // 每用戶獨立 Session
        return "redirect:/home";
    }
    return "login";
}

// 後續方法取得當前用戶
@RequestMapping("/profile")
public String profile(HttpSession session, Model model) {
    User user = (User) session.getAttribute("currentUser");
    model.addAttribute("user", user);
    return "profile";
}

進階:攔截器自動注入

實作 HandlerInterceptor,在 preHandle 從 Session 取出用戶物件,放入 ThreadLocal 或請求屬性,Controller 直接取用,避免重複代碼。

關於 Hibernate 實體與 Session 的補充

  • Hibernate Session(資料庫會話)與 HttpSession(Web 會話)是完全不同概念,切勿混淆。
  • 實體類別若為 JPA/Hibernate 實體,脫管狀態下存入 HttpSession 需注意序列化(實作 Serializable)與懶載入問題(建議登入時初始化所需關聯)。
  • 分散式部署時,需配置 Session 複製(Sticky Session 或 Redis 儲存 Session)。

總結原則

  • 請求範圍資料 → 請求參數 / Model / Request Attribute。
  • 用戶會話資料 → HttpSession。
  • 全域單例資料 → Spring Bean (Service/Repository/Component),必須是線程安全的無狀態物件。

堅持「無狀態 Controller + Session 儲存用戶狀態」的架構原則,能避開 Java Web 開發中最經典的並發 Bug。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved