1.为什么选择freeMarker
1.导出的word模板固定,只是数据改变
2.快速简单
2.freeMarker是什么
FreeMarker是一个用Java语言编写的模板引擎,它基于模板来生成文本输出。FreeMarker与Web容器无关,即在Web运行时,它并不知道Servlet或HTTP。它不仅可以用作表现层的实现技术,而且还可以用于生成XML,JSP或Java 等。
目前企业中:主要用Freemarker做静态页面或是页面展示
3.怎么使用freemarker
- 引入jar,这里用的是org.freemarker.freemarker下
//引入freemarker
compile group: 'org.freemarker', name: 'freemarker', version: '2.3.28'
- 模板生成和创建的工具类
package com.xxxx.xxxxx.util;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.core.io.ClassPathResource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.Map;
/**
* word 文档生成和下载工具类
*/
public class WordExprotUtils {
/**
* 浏览器下载 word文档
* @param dataMap 用map集合来保存,word中需要加载展示的动态数据
* @param templateName word模板名称,例如:complainTemplate.ftl
* @param filePath 文件生成word文件的目标路径,例如:C:\Users\WangChong\Desktop(我们的桌面路径)
* @param fileName 文件生成word文件名称
* @param fileSuffixName 文件生成word文件名称的后缀名
*/
public static void downLoadWord(Map<?,?> dataMap,String templateName,String filePath,String fileName,String fileSuffixName,HttpServletResponse response){
File file = null;
InputStream fin = null;
ServletOutputStream out = null;
try {
//生产word文件
file = createaWord(dataMap,filePath,fileName,fileSuffixName,templateName);
//浏览器下载方式(下载的文件名可以自定命名,这里使用上一步word文件名)
fin = new FileInputStream(file);
response.setCharacterEncoding("utf-8");
response.setContentType("application/msword");
response.setHeader("Content-Disposition", "attachment;filename=".concat(String.valueOf(URLEncoder.encode(fileName+fileSuffixName, "UTF-8"))));
out = response.getOutputStream();
byte[] buffer = new byte[1024]; // 读写缓冲区
int bytesToRead = -1;
while((bytesToRead = fin.read(buffer)) != -1) {
out.write(buffer, 0, bytesToRead);// 通过循环将读入的Word文件的内容输出到浏览器中
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(fin != null) {
fin.close();// 关闭文件输入流
}
if(out != null) {
out.close();// 关闭文件输出流
}
if(file != null) {
file.delete(); // 删除临时文件
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
*创建word文档
* @param dataMap 用map集合来保存,word中需要加载展示的动态数据
* @param filePath 生成word文件的目标路径,例如:C:\Users\WangChong\Desktop(我们的桌面路径)
* @param fileName 生成word文件名称 例如:建议详情
* @param fileSuffixName 生成word文件名称的后缀名 例如:.doc 或 .docx
* @param templateName word模板名称,例如:complainTemplate.ftl
* @return file 返回创建的文件
*/
private static File createaWord(Map<?, ?> dataMap,String filePath,String fileName,String fileSuffixName,String templateName) {
Template freemarkerTemplate = null;
File file = null;
FileOutputStream fileOutputStream = null;
Writer writer = null;
File templateFile = null; //模板文件
try {
//1.配置类配置
Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);//初始化配置 需要指定配置的版本
configuration.setDefaultEncoding("utf-8");//设置默认的编码方式为utf-8
//---------------------------------解决jar获取不到资源路径文件[开始]--------------------------------
//解决思路:将模板放置在磁盘上读取
// 首先获取类路径下的模板文件将其转化为输入流的方式
// 然后在使用的计算上创建一个空的模板文件,这个文件可以是作为临时文件(即创建完使用后删除),也可以作为电脑磁盘上的永久文件。这里使用永久文件,防止频繁创建删除消耗磁盘寿命。
// 再然后 将 上面的输入流复制到创建的模板文件。
ClassPathResource classPathResource = new ClassPathResource("/templates/freeMarkerTemplate/"+templateName);
InputStream inputStream = classPathResource.getInputStream();//先转输入流
String templateDir = filePath+"/freeMarkerTemplate";//模板文件目录
File dir = new File(filePath+"/freeMarkerTemplate");//目录不存在则创建
if (!dir.exists()){
dir.mkdirs();
}
templateFile = new File(templateDir+File.separator+templateName);//生成模板文件
templateFile.createNewFile();//当且仅当不存在具有此抽象路径名指定名称的文件时,不可分地创建一个新的空文件。
FileUtils.copyInputStreamToFile(inputStream, templateFile);//将流复制到目标文件后并关闭流
IOUtils.closeQuietly(inputStream);//手动关闭
//---------------------------------解决jar获取不到资源路径文件[结束]--------------------------------
//2.设置模板
configuration.setDirectoryForTemplateLoading(dir);//注意这里放的是模板文件的目录,而不是具体到模板文件
//3.获取模板
freemarkerTemplate = configuration.getTemplate(templateName);
//4.生成Word文档
file = new File(templateDir+File.separator+fileName+fileSuffixName);//生成的word文档绝对路径
fileOutputStream = new FileOutputStream(file);
writer = new OutputStreamWriter(fileOutputStream, "utf-8");// 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开
freemarkerTemplate.process(dataMap, writer);//生成word文档
} catch (TemplateException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(fileOutputStream != null){
fileOutputStream.close();//关闭文件输出流
}
if(writer != null){
writer.close();//关闭写入流
}
// if(null != somethingFile){
// somethingFile.delete();//删除模板文件,这里不删除
// }
} catch (IOException e) {
e.printStackTrace();
}
}
return file;
}
}
- 制作模板----.ftl文件
1.打开word ,绘制好模板样式,并在要动态展示的地方输入对应的变量名称。例如:${name}
2.另存为‘xml文件(*.xml)’文件
3.用编译器打开上一步的文件,检查变量是否都对(即和原来给的形式一样:例如${name} 符号之间没有多余的字符,如果有要将其删除)
4.重命名为以.ftl为后缀的文件。
参考文章:
https://www.jianshu.com/p/20fd71b2e6a0