最近需要将jsp部分页面导出为word文件,环境是Spring+SpringMVC+Hibernate。
我使用的是FreeMarker模板引擎来完成。这是FreeMarker的中文参考手册,感兴趣的看一下。http://freemarker.foofun.cn/
好啦,接下来正式动手之前我们需要把相应的jar包下载好并导入,下面是最新的链接。
https://freemarker.apache.org/freemarkerdownload.html
我们要做的事情其实很简单,准备一个word模板,编写Controller文件,编写DocUtil工具类 以及提供导出的test.jsp。
1.我们先新建一个需要导出的word文档,在插入数据的地方用${数据}的形式替代,例如这样
我们创建好了需要后另保存为xml格式。
打开test.xml大约是这样,
注意:有时候因为排版的问题,可能${数据}会被拆开,我们调整一下就好。
之后另存为ftl文件,我们的模板文件就完成了,再放在我们的项目目录下就好了,这里我在项目根目录下创建了freemarker.template文件夹来存放模板。
2.现在可以开始编写DocUtil工具类了,我就直接直接贴代码了。
package com.rsp.core.util; import java.io.*; import freemarker.template.Template; import freemarker.template.Configuration; import java.util.HashMap; import java.util.Map; public class DocUtil { private static Configuration configuration = null; private static Map<String, Template> allTemplates = null; static { configuration = new Configuration(); configuration.setDefaultEncoding("utf-8"); configuration.setClassForTemplateLoading(DocUtil.class, "/freemarker/template"); allTemplates = new HashMap<>(); try { allTemplates.put("test", configuration.getTemplate("test.ftl")); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e); } } private DocUtil() { throw new AssertionError(); } public static File createDoc(Map<?, ?> dataMap, String type) { String name = "temp" + (int) (Math.random() * 100000) + ".doc"; File f = new File(name); Template t = allTemplates.get(type); try { // 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开 Writer w = new OutputStreamWriter(new FileOutputStream(f), "utf-8"); t.process(dataMap, w); w.close(); } catch (Exception ex) { ex.printStackTrace(); throw new RuntimeException(ex); } return f; } }
3.Controller类方法
@RequestMapping(value="/exportWord") @ResponseBody public void exportword(HttpServletRequest req,HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("utf-8"); Map<String,Object> map=new HashMap<String,Object>(); Enumeration<String> paramNames=req.getParameterNames(); //通过循环将表单元素放入键值对 while(paramNames.hasMoreElements()){ String key=paramNames.nextElement(); String value=req.getParameter(key); map.put(key,value); } DocUtil doc=new DocUtil(); File file=null; InputStream fin=null; ServletOutputStream out=null; try { file=DocUtil.createDoc(map,"test"); fin = new FileInputStream(file); resp.setCharacterEncoding("utf-8"); resp.setContentType("application/msword"); // 设置浏览器以下载的方式处理该文件默认名为test.doc resp.addHeader("Content-Disposition", "attachment;filename=test.doc"); out = resp.getOutputStream(); byte[] buffer = new byte[512]; // 缓冲区 int bytesToRead = -1; // 通过循环将读入的Word文件的内容输出到浏览器中 while((bytesToRead = fin.read(buffer)) != -1) { out.write(buffer, 0, bytesToRead); } }finally { if(fin!=null) fin.close(); if(out!=null) out.close(); if(file!=null) file.delete(); } }
4.test.jsp,注意这里的name属性要与word里的数据名一样,不然会报错。
<form name="mainform" action="${pageContext.request.contextPath}/news/exportWord" method="post">
<div id="main-box">
<div class="title"> 个人信息 </div> <div class="body">
<p>姓名:<input name="name"type="text" style="width: 301px;"></p>
<p>性别:<input name="sex" type="text" style="width: 301px;"></p>
<p>年龄:<input name="age" type="text" style="width: 301px;"></p>
<input type="submit" value="导出">
</div>
</form>
好了,至此基本就完成了。还有图片的插入也很简单,这里就不多说了。