Java,Jsp,模式及框架
Web技术
Web服务器
浏览器相关
SQL语言
数据库
开发环境
软件开发及管理
网站SEO
短信及邮件服务
网页设计
电脑、硬件及网络
协同管理平台问题
电子商务
前沿技术及趋势
  当前位置:首页 - 知识积累 - Java,Jsp,模式及框架
DisplayTag导出Excel的处理过程
时间:2016年04月12日 

    项目中需要将查询结果导出成Excel,由于使用了DisplayTag,知道这个标签库具有导出Excel的功能,不过之前一直没有使用过,刚好今天体验一把。
使用实在是太Easy了,只需要在display:table标签上设置一下参数,export="true",就可以在表格下边看到导出Excel的链接了,其他什么都不用做!

    对他的实现方式有点好奇,遂查看一下这个导出功能的链接,乖乖,那是相当简洁啊,就是把我这个页面的全部参数添加到URL里,然后附加上了几个奇怪数字组成的参数,估计就是DisplayTag用来识别我要做导出操作的了。从这个链接来看,做导出操作时还是要到我这个Action去进行逻辑处理,但我这个Action输出的内容可是一个完整的HTML,而不是Excel啊,他是怎么实现的呢?带着个大大的问号,开始去挖源代码。顺便提一下,m2eclipse确实方便,不但帮我管理了项目的依赖,还能帮我把源代码拽下来关联到相应的jar,所以我直接在项目依赖里面找到displaytag.jar,就可以查看源代码了。

    代码其实很简单,其实是利用了ServletRsponse的缓存机制,当我们调用response.getWriter().print()方法时,打印的内容是不会立即发送到客户端的,在发送到客户端之前,还可以对其进行操作,哈哈,有点明白了吧?DisplayTag就是利用了这个原理,在TableTag这个类中,导出Excel时,趁ServletResponse还没有提交到客户端,先执行了一下response.reset()和pageContext.getOut().clearBuffer(),这样就把前面jsp里面输出的所有内容都清除掉了~然后再使用response.setContentType()重新设置文件类型,输出表格内容,完事了再返回Tag.SKIP_PAGE,这样JSP里面剩下的内容也不会再输出了,客户端得到的就完全是在DisplayTag控制下的内容了,牛吧!

    其实这个response.reset以前也见过,读servlet API文档时也看过方法的解释,但如果不是今天看这个Display的源代码,还真不会想到这样子来应用,看来这就是理论和实践的差距呀!!!

    PS:上面这种方法,只适用于输出文本内容。DisplayTag自带的Excel导出工具其实就是输出了一个csv文件,把扩展名改成xls了而已。如果要输出真正的xls文件获者PDF这样的二进制文件,使用上面的方法在某些中间件上就会有问题了。因为原则上response.getOutputStream方法是只能被调用一次的,这在进入jsp处理时就被调用了,而输出PDF文件这样二进制流时又必须使用这个方法,那就出错了。DisplayTag很巧妙的提供了一个Filter,对标准的ServletRepsonse做了一个包装(Wrap),在执行Export导出时,如果是jsp等其他请求执行的response.getOutputStream,就返回自己的一个缓存的OutputStream,而不是真正去调用容器的这个方法。直到执行Export时,才去调用容器的方法,保证这个response.getOutputStream只执行一次。

    DisplayTag的地址:http://displaytag.sourceforge.net/1.2/index.html,很简单,很强大,强烈推荐,可以少写N多表格和分页标签