在struts中用stream导出文件

最近两天,客户要求俺所在的team解决一个问题,把数据用csv的格式下载到本地,不要在服务器留有备份。换句话说就是,从数据库中取得数据,用stream直接向客户端输出文件。

这个任务粗一看很简单,因为在设计export engine的时候,早就考虑到输出不同格式的文件形式,用stream作为一种中间形态,无论是printer,xml,csv,html,screem,只是格式不同而已,数据都可以统一处理。view和model分离,可扩展性很强。

嗯,那么stream从哪里生成呢?可笑我java学了多年,却很少涉及servlet,犯难的时候,经同事提醒,看了一下servlet的API,哦,找到了。HttpSeveltResponse.getOutputStream().Ok,一切解决。测试,输出文件。

晕,怎么有错误。error 500:getOutputStream() has already been called for this response.立刻又看了一下api。在getWrtier method看到这么一句话:

Throws:java.lang.IllegalStateException - if the getOutputStream method has already been called for this response object

看明白了,jsp默认用的输出机制是getWrtier ,而用stream输出用的getOutputStream。两者不能在response同时用,不过两者为什么不能同时用,api却没讲。去sun网站,看jsp规范,看到这么一段话

------------------------------------------------------------------------------------
The JSP container should not invoke response.getWriter() until the time when the first portion of the content is to be sent to the client. This enables a number of uses of JSP, including using JSP as a language to glue actions that deliver binary content, or reliably forwarding to a servlet, or change dynamically the content type of the response before generating content
-------------------------------------------------------------------------------------

呵呵,明白了。getWrtier 其使用的也是stream,但是你export file的时候,stream已经flush了,再调用stream当然有问题了。明白了,对症下药。写一个专门的servlet来负责export file。

structs-config.xml
--------------------------------------------------------------------------------------------
                      <forward name="success"         path="/ExportCsv"/>
--------------------------------------------------------------------------------------------

web.xml
--------------------------------------------------------------------------------------------
<servlet>
      <servlet-name>ExportCsv</servlet-name>
       <servlet-class>ExportCsvServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>ExportCsv</servlet-name>
    <url-pattern>/ExportCsv</url-pattern>
  </servlet-mapping>
----------------------------------------------------------------------------------------------

调试,通过。等等,还有一个问题,在struts的mvc中,ActionServlet负责front controller,负责控制流程,集中访问。那么自定义一个servlet,从架构上来说,很明显不是一个最佳的方法。

那有没有什么既简单又能解决问题的方法呢,仔细看了一下structs-config.xml ,哈哈,被我找到了,<forward>既然是重新定向页面,那么只需要输出文件,并没有什么数据需要重新定向页面刷新显示,那么在程序里面return null就可以了。完美解决问题

教训:解决问题的时候不要想得太多,simple is best.

阅读更多
下一篇books.google.com
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭