FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页、电子邮件、配置文件、源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。
这里介绍如何将生成的word保存到本地,以及从浏览器导出word下载。
1.首先下载freemarker包https://freemarker.apache.org/freemarkerdownload.html >>>>>freemarker.jar,BuildPath到项目中。
2.新建一个word文档test.doc,将模板内容替换成变量,这里变量要一次性写完如${name}。
注意:如果变量和符号没有一次性写完,例如先写${},再统一加上变量名,这时当你打开xml的时候"${name}"的“$” “{}” “name”就会分开,导出时会出错。建议先把整个${name} ${sex}...写在txt中再copy进来。
3.将test.doc另存为xml
4.用Notepad++打开test.xml,Ctrl+F 搜索$, 检查变量和符号是否正常,变量后面可以都加上?if_exists用于判空。
5.然后将test.xml的后缀名改成ftl,即test.ftl模板,将模板放到项目中去。
6.定义一个处理类DocumentHandler,该类包含两个导出方法
package cn.hpc.ssm.common;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
public class DocumentHandler {
//Configuration存储一些全局常量和常用设置
private Configuration configuration = null;
//构造函数生成实例并设置编码
public DocumentHandler() {
configuration = new Configuration();
configuration.setDefaultEncoding("utf-8");
}
/**
* 导出word文档,导出到本地
* @param tempName,要使用的模板
* @param docName,导出文档名称
* @param dataMap,模板中变量数据
* @param outFile,输出文档路径
*/
public boolean exportDoc(String tempName,Map<?, ?> dataMap,File outFile) {
boolean status = false;
// 设置模本装置方法和路径,FreeMarker支持多种模板装载方法。可以重servlet,classpath,数据库装载,
configuration.setClassForTemplateLoading(this.getClass(), "/cn/hpc/ssm/template");
Template t = null;
try{
// tempName.ftl为要装载的模板
t = configuration.getTemplate(tempName+".ftl");
t.setEncoding("utf-8");
} catch (IOException e) {
e.printStackTrace();
}
Writer out = null;
try{
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"));
status = true;
}catch(Exception e1) {
e1.printStackTrace();
}
try{
t.process(dataMap, out);
out.close();
}catch(TemplateException e){
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return status;
}
/**
* 导出word文档,响应到请求端
* @param tempName,要使用的模板
* @param docName,导出文档名称
* @param dataMap,模板中变量数据
* @param resp,HttpServletResponse
*/
public boolean exportDoc(String tempName, String docName, Map<?, ?> dataMap, HttpServletResponse resp) {
boolean status = false;
ServletOutputStream sos = null;
InputStream fin = null;
if (resp != null) {
resp.reset();
}
// 设置模本装置方法和路径,FreeMarker支持多种模板装载方法。可以重servlet,classpath,数据库装载。参数2为模板路径
configuration.setClassForTemplateLoading(this.getClass(), "/cn/hpc/ssm/template");
Template t = null;
try {
// tempName.ftl为要装载的模板
t = configuration.getTemplate(tempName + ".ftl");
t.setEncoding("utf-8");
} catch (IOException e) {
e.printStackTrace();
}
// 输出文档路径及名称 ,以临时文件的形式导出服务器,再进行下载
String name = "temp" + (int) (Math.random() * 100000) + ".doc";
File outFile = new File(name);
Writer out = null;
try {
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"));
status = true;
} catch (Exception e1) {
e1.printStackTrace();
}
try {
t.process(dataMap, out);
out.close();
} catch (TemplateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
fin = new FileInputStream(outFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// 文档下载
resp.setCharacterEncoding("utf-8");
resp.setContentType("application/msword");
try {
docName = new String(docName.getBytes("UTF-8"), "ISO-8859-1");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
resp.setHeader("Content-disposition", "attachment;filename=" + docName + ".doc");
try {
sos = resp.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
byte[] buffer = new byte[512]; // 缓冲区
int bytesToRead = -1;
// 通过循环将读入的Word文件的内容输出到浏览器中
try {
while ((bytesToRead = fin.read(buffer)) != -1) {
sos.write(buffer, 0, bytesToRead);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fin != null)
try {
fin.close();
} catch (IOException e) {
e.printStackTrace();
}
if (sos != null)
try {
sos.close();
} catch (IOException e) {
e.printStackTrace();
}
if (outFile != null)
outFile.delete(); // 删除临时文件
}
return status;
}
}
代码中的“/cn/hpc/ssm/template”是存放模板的包路径
7.添加Junit测试方法,右键 Run As >>> Junit Test
//导出到本地
@Test
public void exportWordTest1(){
File file =new File("d:\\test.doc");
if(!file.exists())
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
Map<String, Object> map =new HashMap<>();
//这里的键要对应模板中的变量
map.put("name", "李相赫");
map.put("sex", "男");
map.put("native", "广东");
map.put("birthday", "2018-8-13");
map.put("ecducation", "本科");
map.put("political", "党员");
map.put("university", "广东科学技术职业学院");
map.put("major", "物联网应用技术");
map.put("email", "lixianghe@163.com");
map.put("phone", "18825455689");
map.put("qq", "1044558545");
System.out.println(map.toString());
// test t =new test();
// t.setBirthday("2018-8-13");
// t.setEducation("本科");
// t.setEmail("lixianghe@163.com");
// t.setNative("广东1");
// t.setMajor("物联网应用技术");
// t.setName("李相赫");
// t.setPhone("18825455689");
// t.setPolitical("党员");
// t.setQq("1044558545");
// t.setSex("男");
// t.setUniversity("广东科学技术职业学院");
// Map<String, Object> maps =Utils.object2Map(t);
// System.out.println(maps.toString());
boolean b =new DocumentHandler().exportDoc("test", map, file);
System.out.println(b);
}
运行结果,D盘目录多了test.doc,打开
9.测试浏览器端请求的方法,添加一个springmvc的接口方法
@RequestMapping(value="/exportWord.action")
public void exportWordTest(HttpServletRequest req, HttpServletResponse resp){
System.out.println("使用freemark导出Word");
Map<String, Object> map =new HashMap<>();
map.put("name", "李相赫");
map.put("sex", "男");
map.put("native", "广东");
map.put("birthday", "2018-8-13");
map.put("ecducation", "本科");
map.put("political", "党员");
map.put("university", "广东科学技术职业学院");
map.put("major", "物联网应用技术");
map.put("email", "lixianghe@163.com");
map.put("phone", "18825455689");
map.put("qq", "1044558545");
boolean b =new DocumentHandler().exportDoc("test", "个人信息", map, resp);
System.out.println(b);
}
10.浏览器发出请求
下载到桌面打开可以看到相同的内容
2019年9月27日09:33:19 新增
注意事项:在word另存为xml时,要保存为word2003.xml文档,这样的模板可以兼容wps与office
tips.
在编辑xml文件时,可以使用在线代码格式化工具,格式化完的代码更容易看清楚结构,减少出错几率
来源:CSDN
作者:飞鱼的幻想之旅
链接:https://blog.csdn.net/weixin_35654814/article/details/81628148