介绍一个专注于Java的网站:Java之音
http://freemarker.org/
Freemarker官网,英文,可以用谷歌浏览器的自动翻译,英文水平高的忽略这句。。
简单来说:FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯Java编写。FreeMarker被设计用来生成HTMLWeb页面,特别是基于MVC模式的应用程序。
这里使用freemarker生成Word文档,非常方便。
惯例,先看看Demo整体结构:
Demo结构:
这里要引入freemarker包,通过Freemarker加载word文档的模版
生成Word文档类ToCreateDoc:
package org.javasun.createDoc; import java.io.IOException; import java.io.Writer; import java.util.Map; import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException; public class ToCreateDoc { private Configuration configuration = null; public ToCreateDoc() { configuration = new Configuration(); configuration.setDefaultEncoding("UTF-8"); } public void createDoc(Writer out, Map<String, Object> dataMap, String ftlName) { configuration.setClassForTemplateLoading(getClass(), "/ftl"); try { Template t = null; t = configuration.getTemplate(ftlName,"UTF-8"); t.process(dataMap, out); } catch (TemplateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
Servlet,填数据发送客户端处理:
package org.javasun.servlet; import java.io.IOException; import java.io.Writer; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.javasun.createDoc.ToCreateDoc; @WebServlet("/download") public class DownloadServlet extends HttpServlet { public DownloadServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 设置response类型 String fileName = "test.doc"; // 设置响应正文的MIME类型 response.setCharacterEncoding("utf-8"); response.setHeader("Content-Disposition", "attachment;" + " filename=" + fileName); // 获取数据,设置数据 Map<String, Object> dataMap = new HashMap<>(); dataMap.put("company", "XXX百货公司"); dataMap.put("companyname", "XXX批发商"); dataMap.put("addr", "太原市XXXX"); dataMap.put("contact", "张文先生"); dataMap.put("phone", "12345678"); List<Map<String, String>> payList = new ArrayList<>(); for (int i = 1; i < 8; i++) { Map<String, String> iMap = new HashMap<>(); iMap.put("proName", "智能手机" + i + "0"); iMap.put("pay", i * 1000 + ""); iMap.put("num", "105"); iMap.put("total", "100333"); payList.add(iMap); } dataMap.put("itemlist", payList); // 把本地文件发送给客户端 Writer out = response.getWriter(); ToCreateDoc tcd = new ToCreateDoc(); tcd.createDoc(out, dataMap, "demo.ftl"); out.close(); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
Jsp页面测试效果:
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title></title> <script type="text/javascript"> function download_file(url){ if (typeof (download_file.iframe) == "undefined") { var iframe = document.createElement("iframe"); download_file.iframe = iframe; document.body.appendChild(download_file.iframe); } download_file.iframe.src = url; download_file.iframe.style.display = "none"; } </script> </head> <body> <button onclick="download_file('download');" >单击生成Word文档</button> </body> </html>
点击按钮,Word文档就会自动下载,下载的文件如图:
我们可以看到,很方便,只要定义好文件模版,就可以将数据库数据导入成文档格式保存或者打印。
那么如何定义模版呢?
将需要的Word文档做好之后(一般是没有数据的一种文档模版格式),选择另存为XML文件,存为XML的目的是方便检查,看看${}占位符的内容是否被分开了(分开之后会导致很多问题,所以要调整格式,修改一下XML文件),之后另存为.ftl模版文件就OK了,在项目中引用就可以实现内容按所想的格式输出。
如何引用?
Freemarker提供了3种加载模板目录的方法。 它使用Configuration类加载模板
3种方法分别是:
public voidsetClassForTemplateLoading(Class clazz, String pathPrefix);
public voidsetDirectoryForTemplateLoading(File dir) throws IOException;
public voidsetServletContextForTemplateLoading(Object servletContext, String path);
分别基于类路径、文件系统以及Servlet Context路径。
注意事项(导出的Word文档很容易出现乱码)如何解决?
我们在做模板导出时需要注意以下三处编码集的设置,有一处没有设置就会导致到处uWord文档出现中文乱码。
(1)configuration.setDefaultEncoding("UTF-8");
(2)Template t =configuration.getTemplate("模板文件","UTF-8");
(3)Writer out = newBufferedWriter(new OutputStreamWriter(文件输出流 fos, "UTF-8"))。
Demo下载地址:https://github.com/guodalin8/ToWordTest