在 Java Web 專案中,用戶登入後的實體物件(如 User)應儲存在 HttpSession 中,而非定義為 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 用戶的資料。
@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 直接取用,避免重複代碼。
Serializable)與懶載入問題(建議登入時初始化所需關聯)。Model / Request Attribute。HttpSession。堅持「無狀態 Controller + Session 儲存用戶狀態」的架構原則,能避開 Java Web 開發中最經典的並發 Bug。