Struts2 下载点取消报异常最终解决办法

 

在我们做struts2文件下载的时候,经常会遇到这种问题:点“打开/保存”一切正常,但当我们点击“取消”时,却报一堆的异常,非常让人头疼,错误如下(每个人的错误估计不太一样,以我的为例):
Java代码  
严重: Servlet.service() for servlet default threw exception
java.lang.IllegalStateException
 at org.apache.catalina.connector.ResponseFacade.sendError(ResponseFacade.java:407)
 at org.apache.struts2.dispatcher.Dispatcher.sendError(Dispatcher.java:770)
 at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:505)
 at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)
 at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:91)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
 at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
 at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
 at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
 at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
 at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
 at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
 at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
 at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
 at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
 at java.lang.Thread.run(Thread.java:619)

异常原因分析:
[stream对应的类是org.apache.struts2.dispatcher.StreamResult,该类的处理过程如下:
1.配置其中result标签下的各个参数
2.从服务器中获取输入流,并同时与客户端建立输出流(服务器与客户端链接通过Socket进行连接)
3.当点击“保存”或“打开”时,开始传输数据。如果点击“取消”,关闭所有的流。
  这里要注意的是,但是实际发现Socket并没有断开!并且流也没有关闭!这一点非常重要!
  所以在JSP容器通过Response获取输出流之前,前面的流并没有关闭,所以会造成该异常的报出。
我在CSDN上搜了一个人的解决方法,他是这么解决的:
Java代码  
<package name="default" extends="json-default" namespace="/">   
  <!-- 定义全局Result -->   
  <global-results>   
     <result name="client-abort-exception">/null.jsp</result>   
  </global-results>   
</package>   
  
<package name="main" extends="default" namespace="/">   
<action name="download" class="fileAction" method="download">   
    <exception-mapping result="client-abort-exception" exception="org.apache.catalina.connector.ClientAbortException"></exception-mapping>   
    <param name="savePath">/upload/download</param>   
    <!-- 文件下载配置结果类型为stream的结果 -->   
    <result name="download" type="stream">   
      <param name="inputName">targetFile</param>   
      <!-- 指定保存还是直接打开要下载的文件默认为:直接打开,这里配置保存 -->   
      <param name="contentDisposition">attachment;filename="${downloadFileName}"</param>   
      <!-- 指定下载文件的缓存大小 -->   
      <param name="bufferSize">4096</param>   
    </result>   
</action>   
</package>  
<package name="default" extends="json-default" namespace="/">       
  <!-- 定义全局Result -->
  <global-results>
     <result name="client-abort-exception">/null.jsp</result>
  </global-results>
</package>
<package name="main" extends="default" namespace="/">
<action name="download" class="fileAction" method="download">
    <exception-mapping result="client-abort-exception" exception="org.apache.catalina.connector.ClientAbortException"></exception-mapping>
    <param name="savePath">/upload/download</param>
    <!-- 文件下载配置结果类型为stream的结果 -->
    <result name="download" type="stream">
      <param name="inputName">targetFile</param>
      <!-- 指定保存还是直接打开要下载的文件默认为:直接打开,这里配置保存 -->
      <param name="contentDisposition">attachment;filename="${downloadFileName}"</param>
      <!-- 指定下载文件的缓存大小 -->
      <param name="bufferSize">4096</param>
    </result>
</action>
</package>
也就是说,如果抛出了ClientAbortException异常,那就跳转到“null.jsp”这个页面,这个页面中什么内容都没有。虽然这种方法暂时可行,但是当遇到其他异常的时候,也就是非ClientAbortException之后,这个方法就不可行了。我之前也是参照这种方法配置,但昨天我重新启动应用的时候,点击“取消”居然还报错,错误就是上面的一堆“java.lang.IllegalStateException”,而且这种方法也是一种逃避的方法,也就是置之不理。这并不可取,解决问题就要解决彻底明了,逃避是没用的,经过网上大师们的分析测试,最终解决办法如下:
1.下载一个插件struts2-sunspoter-stream-1.0.jar(附件中有下载)。
2.将附件解压获取struts2-sunspoter-stream-1.0.jar,并复制在/WEB-INF/lib下。
3.在原有的struts.xml的基础上进行相应的配置,配置如下:
Java代码  
 <!-- 下载处理 -->
 <package name="file" extends="authority-default">
 <result-types>  
  <result-type  name="streamx" class="com.sunspoter.lib.web.struts2.dispatcher.StreamResultX"/>  
 </result-types>
  <action name="download" class="org.usc.file.DownloadAction">
   <result name="success" type="streamx">   
   <!--  <result name="success" type="stream">-->
     <param name="contentType">application/octet-stream;charset=ISO8859-1</param>
    <param name="contentDisposition">attachment;filename="${fileName}"</param>
    <param name="inputName">downloadFile</param>
   </result>
   <result name="error">error.jsp</result>
  </action>
 </package>

在这种方式下,只需添加一个result-type,将原有的result中type改为“streamx”,其他一律不变,在这种情况下,点击“取消”的同时也关闭了流,不会再报出该异常。
如果出现log4j的警告,比如:
21:23:44,676  WARN StreamResult:45 - StreamResultX Warn : socket write error   
出现该警告说明正确执行,该警告说明,Socket非正常中断,但是流确实已经关闭,自此再也不用看到上面出现的讨厌异常结果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值