在项目中不免和各类数据报表打交道,如导出XX申请表,登记表,推荐表之类。就能够经过现有信息导出Word文档。基于Java语言来导出Word文档的方式也有不少种,如Jacob,Apache POI,Freemarker,PageOffice,java2word 等等。。。。java
在这里将经过Freemarker这个模板引擎来实现导出 Word,项目不限于Swing,SSH,SSM,Spring Boot 之类的。。。。。。。。。。mysql
Freemarker介绍
首先说一下Freemarker是个什么东西:程序员
FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页、电子邮件、配置文件、源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员能够嵌入他们所开发产品的组件。
FreeMarker是免费的,基于Apache许可证2.0版本发布。其模板编写为FreeMarker Template Language(FTL),属于简单、专用的语言。须要准备数据在真实编程语言中来显示,好比数据库查询和业务运算, 以后模板显示已经准备好的数据。在模板中,主要用于如何展示数据, 而在模板以外注意于要展现什么数据 。
------百度百科web总的来讲:模板 + 数据模型 = 输出spring
看不懂也不要紧,看一个简单的例子:一般咱们在Java Web开发的时候,实现一个JSP页面的输出须要编写一个JSP文件《xxxx.jsp》,实际上这个JSP文件主要包含了两部份内容:
HTML+CSS+JavaScript构成的页面框架 + 用来动态显示数据库数据的Java代码(通常来讲直接写Java代码是很是不美观且修改复杂的事情,不符合MVC开发模式,因此会用JSTL标签来代替直接写Java代码)
sql
在Freemarker中也有一套相似于JSTL的标签,其实简单来讲freemarker就是用来代替jsp来作处理,由于咱们若是用JSP的话,是须要WEB容器的,如tomcat,JSP在第一次执行的时候会被编译转换成Servlet类,以后的每次修改都要编译和转换。而FreeMarker模板技术并不存在编译和转换的问题,而且与容器无关。咱们在非web项目下也不必再引入一个web容器了。
数据库
示例用的项目搭建
下面进入正题:
首先建立一个项目,在这里的项目能够为Java swing,Javaweb的SSM,Springboot等项目都是没问题的。我仍是直接用SpringBoot项目实现这个功能了。
首先用IDEA建立一个Spring Boot项目编程
用其余IDE的也能够在https://start.spring.io网站上面直接下载一个springboot项目浏览器
下一步填完信息,这里我用默认的信息了tomcat
开始选择所须要的插件依赖,也就是jar包,都是经过maven管理的,上图有说明
1.
2. 选择Spring Web,就是SpringMVC
3. 选择用哪一个模板引擎,这里用Freemarker
4. 选择数据库框架,这里用mybaits+mysql
5. 下一步,选择项目路径,点击完成就能够了
Freemarker主要依赖的jar包是
# Springboot 提供的 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency> # 也能够选择其余版本如: <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.30</version> </dependency> # 网址: https://mvnrepository.com/artifact/org.freemarker/freemarker
FTL模板制做
项目搭建好以后,开始制做FTL模板,此次选择一个XXX推荐表来实现:
如Word文档:
开始制做模板:
首先,咱们须要在模板上面添加占位符,${XXXXX}。这里全用了拼音简写
添加好占位符以后,将该Word文档另存为XML格式的文件
修改一下文件名称,保存
即获得一个XML文件
打开观察一下,正常
接下来,利用文本编辑器打开这个文件,如Notepad++、Sublime Text、EditPlus、UltraEdit什么都行,我这里用VSCode。如图
直接搜索前面添加的占位符${xxxx},这里可能会出现一些问题,如符号和花括号分离,这时候就得对它进行修改,恢复原样
修改后
等检查一遍没问题以后呢,就修改完成了,开始进入下一步修改文件后缀
代码编写
接下来开始代码编写部分,通常来讲这里都是用数据库的数据做为导出数据。但因为麻烦就不写数据库部分了,在这里直接用提交表单的数据来进行导出。
1.回到项目上,新建一个实体类,TableData.java ,将占位符标识做为类属性,生成get、set方法。。。。。发现院系YX和邮箱YX重复了,修改邮箱为DZYX
2. 新建简单的测试页面
3. 编写导出工具类
首先将实体类封装为导出数据所需的map,建立数据模型
**注意:
**在这里直接用的是封装实体类,因此在模板里面也须要改一下占位符,在前面加上对象名${DZYX}
变为${tableData.DZYX}
,用文本编辑器一键搜索${
替换便可 )
编写方法,建立freeMarker配置实例,建立数据模型,加载模板,输出
/** * 导出Word文件 * * @param tableData * @param request * @param response * @throws Exception */ public InputStreamSource exportToWord(TableData tableData, HttpServletRequest request, HttpServletResponse response) throws Exception { // 纠正编码 request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("utf-8"); // ** 初始化配置文件**//* Configuration configuration = new Configuration(); // ** 设置编码 **//* configuration.setDefaultEncoding("utf-8"); // ** ftl文件的路径**//* String fileDirectory = "D:\\"; //将模板文件放到了D盘下 // 加载模板文件 configuration.setDirectoryForTemplateLoading(new File(fileDirectory)); // 加载模板,经过Word转XML文件转换过来的 Template template = configuration.getTemplate("FreemarkerTest.ftl"); // 准备数据 Map<String, Object> dataMap = data(tableData); // 指定输出word文件的路径 // 调用工具类WordUtils的createDoc方法生成Word文档 InputStreamSource file = UtilTest.createDoc(dataMap, template); InputStream fin = file.getInputStream(); ServletOutputStream out; response.setContentType("application/msword"); // 设置浏览器如下载的方式处理该文件 response.setHeader("content-disposition", "attachment;filename=document.doc"); out = response.getOutputStream(); // 缓冲区 byte[] buffer = new byte[512]; int bytesToRead; // 经过循环将读入的Word文件的内容输出到浏览器中 while ((bytesToRead = fin.read(buffer)) != -1) { out.write(buffer, 0, bytesToRead); } fin.close(); if (out != null) { out.close(); } return file; }
建立word文件
/** * 建立word文件 * * @param dataMap * @param template * @return * @throws TemplateException * @throws IOException */ public static InputStreamSource createDoc(Map<String, Object> dataMap, Template template) throws TemplateException, IOException { //生成随机的合同名称 StringWriter out1 = new StringWriter(); Writer out = new BufferedWriter(out1, 10240); //将数据输出到模板 template.process(dataMap, out); out.close(); out1.close(); return new ByteArrayResource(out1.toString().getBytes(StandardCharsets.UTF_8)); }
4.编写控制层
运行项目,跳到测试页面,填写相应信息
提交表单,会弹出下载框
将文件下载到本地,打开,能够看到已经填充完成,
至此,基于Java和freemarker实现的Word文件导出功能已经实现了
再回顾一下步骤:
1.编辑好格式的Word文档 1份
2.将Word文档里须要填充的地方加上占位符${xxxx}
3.将编辑好占位符的文档另存为XML格式Word 2003 XML文档,并重命名,用英文命名
4.利用文本编辑器打开该XML文件检查,搜索第二步编辑的占位符,遇到$和 { } 分离的状况则进行修改。检查完毕后保存退出。
5.将检查完成的XML文件修改后缀名为 xxx.ftl
6.模板编辑完成
7.创建Java项目,引入jar包
<dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.30</version> </dependency>
8.编写对应数据的实体类
9.编写测试页面
10.编写导出的工具类(核心
),并修改模板对应的占位符,有须要的话
11.编写控制层
12.测试
代码
项目代码–工具类
package com.hh.onlinelearning.util; import com.hh.onlinelearning.entity.TableData; import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException; import org.springframework.core.io.ByteArrayResource; import org.springframework.core.io.InputStreamSource; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; public class UtilTest { /** * 导出Word文件 * * @param tableData * @param request * @param response * @throws Exception */ public InputStreamSource exportToWord(TableData tableData, HttpServletRequest request, HttpServletResponse response) throws Exception { // 纠正编码 request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("utf-8"); // ** 初始化配置文件**//* Configuration configuration = new Configuration(); // ** 设置编码 **//* configuration.setDefaultEncoding("utf-8"); // ** ftl文件的路径**//* String fileDirectory = "D:\\"; // 加载模板文件 configuration.setDirectoryForTemplateLoading(new File(fileDirectory)); // 加载模板,经过Word转XML文件转换过来的 Template template = configuration.getTemplate("FreemarkerTest.ftl"); // 准备数据 Map<String, Object> dataMap = data(tableData); // 指定输出word文件的路径 // 调用工具类WordUtils的createDoc方法生成Word文档 InputStreamSource file = UtilTest.createDoc(dataMap, template); InputStream fin = file.getInputStream(); ServletOutputStream out; response.setContentType("application/msword"); // 设置浏览器如下载的方式处理该文件 response.setHeader("content-disposition", "attachment;filename=document.doc"); out = response.getOutputStream(); // 缓冲区 byte[] buffer = new byte[512]; int bytesToRead; // 经过循环将读入的Word文件的内容输出到浏览器中 while ((bytesToRead = fin.read(buffer)) != -1) { out.write(buffer, 0, bytesToRead); } fin.close(); if (out != null) { out.close(); } return file; } /** * 构造数据,key-value * * @param tableData * @return */ public Map<String, Object> data(TableData tableData) { Map<String, Object> dataMap = new HashMap<>(); dataMap.put("tableData", tableData); return dataMap; } /** * 建立word文件 * * @param dataMap * @param template * @return * @throws TemplateException * @throws IOException */ public static InputStreamSource createDoc(Map<String, Object> dataMap, Template template) throws TemplateException, IOException { //生成随机的合同名称 StringWriter out1 = new StringWriter(); Writer out = new BufferedWriter(out1, 10240); //将数据输出到模板 template.process(dataMap, out); out.close(); out1.close(); return new ByteArrayResource(out1.toString().getBytes(StandardCharsets.UTF_8)); } }