每個作用域隱式對象均提供 removeAttribute(String name) 方法,參數為 <jsp:useBean id="..."> 指定的 id。
| 作用域 | 移除代碼 | 典型觸發時機 |
|---|---|---|
| page | pageContext.removeAttribute("beanId"); | 頁面邏輯結束前主動釋放 (極少用) |
| request | request.removeAttribute("beanId"); | forward 後不想傳遞給下一資源 |
| session | session.removeAttribute("beanId"); | 用戶登出、清空購物車、權限變更 |
| application | application.removeAttribute("beanId"); | 管理員刷新快取、模塊卸載、容器關閉 |
CountBean.java (同前)counter.jsp<%@ page contentType="text/html;charset=utf-8" %>
<jsp:useBean id="cou" class="javabean01.CountBean" scope="session"/>
<html><body>
<h3>第 <jsp:getProperty name="cou" property="count"/> 次訪問!</h3>
<% session.removeAttribute("cou"); %> <!-- 立即銷毀 -->
<p>已移除 session 中的 cou,下次訪問將重新計數。</p>
</body></html>
**效果**:每次刷新頁面計數永遠為 1,控制台每次印「新實例誕生」。
而非在 JSP 散落移除代碼,應集中在 **Listener** 管理生命週期:
@WebListener
public class BeanLifecycleListener implements HttpSessionListener, ServletContextListener {
@Override public void sessionDestroyed(HttpSessionEvent se) {
// Session 銷毀時自動清理 (容器會自動移除所有屬性)
// 此處可執行額外資源釋放:關閉連接、釋放鎖、發送事件
}
@Override public void contextDestroyed(ServletContextEvent sce) {
// 應用關閉:關閉線程池、資料庫連接池、緩存客戶端
}
}
| 框架 | 機制 | 開發者責任 |
|---|---|---|
| Spring | Scope 代理 + DestructionCallback + @PreDestroy | 正確聲明 @RequestScope 等,容器自動銷毀 |
| CDI | Context 生命週期事件 + @PreDestroy | 實現 Serializable (Session/Application),容器自動處理 |
| Jakarta Faces | View/Flash/Flow/Session/Application Scope 自動管理 | 使用 @ViewScoped 等註解,無需手工移除 |
removeAttribute 後仍持有引用:局部變數/集合仍引用 Bean,阻礙 GC。移除後置 null。ConcurrentHashMap.computeIfAbsent 或鎖保護。session.invalidate() 會銷毀整個 Session (含所有屬性);removeAttribute 僅移除單一屬性。**登出請用 invalidate**。