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

Struts2 Action 單例與多例模式:原理、風險與配置實戰

     編輯:Java 綜合教學

核心結論

Struts2 默認將 Action 配置為單例,但在 Web 開發中強烈建議改為多例,以避免併發請求下的屬性污染問題。

為什麼單例會出問題?

場景還原

  • 用戶 A 提交請求,參數 param1=valueA,Action 實例的 param1 被設置為 valueA。
  • 用戶 B 緊接著提交請求,未包含 param1,Action 實例的 param1 保持上次值 valueA(不會自動重置為 null)。
  • 業務邏輯誤以為用戶 B 也傳了 param1=valueA,導致數據錯亂、權限繞過等嚴重 Bug。

根因:單例模式下,Action 實例屬於類級別,生命周期贏應用上下文。多線程併發訪問同一實例的屬性,無線程隔離。

多例模式如何解決?

  • 每次請求創建新實例,屬性天然隔離,請求結束自動回收(GC)。
  • 雖增加對象創建開銷,但現代 JVM 對短命對象優化極佳,性能影響可忽略;換取的是絕對的線程安全。

配置對比

模式配置示例適用場景
單例<bean id="userAction" class="com.xxx.UserAction" scope="singleton">無狀態服務、工具類、常量持有者
多例<bean id="userAction" class="com.xxx.UserAction" scope="prototype">所有接收請求參數的 Action

Struts2 專用配置方式

在 struts.xml 中直接聲明:

<action name="userAction" class="com.xxx.UserAction" method="execute">
    <!-- 強制多例,Struts2 會忽略 Spring 的 scope 設置 -->
    <param name="className">com.xxx.UserAction</param>
</action>

或在 Spring 配置中顯式指定 scope="prototype",並確保 Struts2 使用 Spring 創建 Bean(需配置 struts.objectFactory = spring)。

最佳實踐清單

  1. 默認所有 Action 設為 prototype,除非極其確定該 Action 完全無狀態。
  2. 避免在 Action 中定義非請求參數的可變實例變量(如計數器、緩存集合)。
  3. 若需跨請求共享數據,改用 Session、Redis 或 ThreadLocal(謹慎)。
  4. 壓測驗證:併發 1000+ 時觀察對象創建率、GC 頻率、響應延遲。

總結

Struts2 Action 單例是歷史遺留默認值,實戰中必須顯式改為多例。這不是優化選項,而是正確性前提。配置成本極低,收益極大——消滅一大類難以復現的併發 Bug。

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