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

Struts 2 文件下載取消報 IllegalStateException 終極解決方案

     編輯:Java 相關知識

問題現象

使用 Struts 2 <result type="stream"> 實現文件下載時,用戶在瀏覽器下載對話框點擊「取消」,伺服器拋出 java.lang.IllegalStateException,堆疊追蹤指向 ResponseFacade.sendError()、Dispatcher.serviceAction()、FilterDispatcher.doFilter() 等。

根因分析

  1. StreamResult 執行流程:配置參數 → 取得輸入流 → 建立輸出流(Socket 連線) → 傳輸資料
  2. 用戶點「取消」 → 瀏覽器關閉 HTTP 連線 → Socket 實際未斷開、流未關閉
  3. Servlet 容器嘗試透過 Response 取得輸出流送錯誤頁面 → 發現流已被佔用/未正確關閉 → 拋出 IllegalStateException

網路上常見但不推薦的規避方案

<global-results>
  <result name="client-abort-exception">/ignored.jsp</result>
</global-results>
<exception-mapping result="client-abort-exception" exception="org.apache.catalina.connector.ClientAbortException"/>

缺點:僅吞掉異常,底層 Socket/流資源仍可能洩漏,治標不治本。

終極解決方案:自定義 StreamResultX

提供一個 4KB 的插件 struts2-sunspoter-stream-1.0.jar,核心類 com.sunspoter.lib.web.struts2.dispatcher.StreamResultX,在用戶取消時主動關閉輸入/輸出流並釋放 Socket。

部署步驟

  1. 下載並解壓取得 struts2-sunspoter-stream-1.0.jar
  2. 放入 WEB-INF/lib
  3. 修改 struts.xml 註冊新 result type 並替換原 stream

struts.xml 配置範例

<package name="default" namespace="/" extends="struts-default">
  <result-types>
    <result-type name="streamx" class="com.sunspoter.lib.web.struts2.dispatcher.StreamResultX"/>
  </result-types>

  <action name="download" class="com.DownloadAction">
    <result name="success" type="streamx">
      <param name="inputName">download</param>
      <param name="bufferSize">4096</param>
      <param name="contentDisposition">filename="${filename}"</param>
      <param name="contentCharSet">UTF-8</param>
    </result>
  </action>
</package>

只需將 type="stream" 改為 type="streamx",其他參數完全相容。

執行效果

啟用 log4j 後,取消下載僅輸出警告,不再拋出異常:

21:23:44,676 WARN StreamResult:45 - StreamResultX Warn : socket write error

含義:Socket 非正常中斷,但流已正確關閉,資源無洩漏。

原理亮點

  • 繼承 StreamResult,重寫 execute() 增加 try-finally 確保流關閉
  • 捕捉 ClientAbortException / SocketException 靜默處理
  • 零侵入業務代碼,僅配置切換

下載連結

附件:struts2-sunspoter-stream-1.0.jar 或訪問 官方下載頁(無需積分)。

適用版本

Struts 2.0.x ~ 2.5.x,已驗證於 Tomcat 6/7/8、Jetty、JBoss、WebLogic。

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