需求背景:将用户提交的活动报名信息生成Word供用户下载。
目前个人对于freemarker的理解是,freemarker是一个模板引擎工具,可以利用它来实现网页的文本输出。
实现功能需要freemarker的jar包。百度都有。本人用的是freemarker-2.3.13.jar,下载完后直接拖进项目的lib下。
1.编写一个freemarker模板,用于网页内容的填充模板。生成模板文件十分的简单。具体做法是,将一个Word中的网页内容填充位置用freenmarker的占位符来代替。
接着保存为xx.xml文件,建议之后再用notepad++打开在检查一遍,检查占位符是否被拆散。一定要保持占位符的完整。
2.然后改为freemarker的模板文件格式xx.ftl.
将ftl文件放入如下图所示的文件路径下:
3.代码实现
controller的代码:
package ffc.controller;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import ffc.controller.util.WordGenerator;
import ffc.po.joins.Joins;
import ffc.service.join.IJoinService;
@Controller
public class JoinController {
@Autowired
IJoinService joinService;
/**
* 报名活动
* @param join
* @param response
* @throws Exception
*/
@RequestMapping("join")
public void join(Joins joins,HttpServletResponse response) throws Exception{
joinService.joinEvent(joins);
response.getWriter().print("ok");
}
/**
* 将报名信息转换为word的方法
* @param resp
* @param req
* @throws Exception
*/
@RequestMapping("download")
public void download(HttpServletResponse response,HttpServletRequest request) throws Exception{
response.setCharacterEncoding("utf-8");
Map<String, Object> map = new HashMap<String, Object>();
Enumeration<String> paramNames = request.getParameterNames();
// 通过循环将表单参数放入键值对映射中
while(paramNames.hasMoreElements()) {
String key = paramNames.nextElement();
String value = request.getParameter(key);
map.put(key, value);
}
// 提示:在调用工具类生成Word文档之前应当检查所有字段是否完整
// 否则Freemarker的模板殷勤在处理时可能会因为找不到值而报错 这里暂时忽略这个步骤了
File file = null;
InputStream fin = null;
ServletOutputStream out = null;
try {
// 调用工具类WordGenerator的createDoc方法生成Word文档
file = WordGenerator.createDoc(map, "join");
fin = new FileInputStream(file);
response.setCharacterEncoding("utf-8");
response.setContentType("application/msword");
// 设置浏览器以下载的方式处理该文件默认名为join.doc
response.addHeader("Content-Disposition", "attachment;filename=join.doc");
out = response.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(); // 删除临时文件
}
}
}
工具类代码:
package ffc.controller.util;
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 freemarker.template.Configuration;
import freemarker.template.Template;
public class WordGenerator {
private static Configuration configuration = null;
private static Map<String, Template> allTemplates = null;
static {
configuration = new Configuration();
configuration.setDefaultEncoding("utf-8");
configuration.setClassForTemplateLoading(WordGenerator.class, "/ffc");
allTemplates = new HashMap<>();
try {
allTemplates.put("join", configuration.getTemplate("join.ftl"));
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
private WordGenerator() {
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;
}
}
页面代码:
<form action="download.action" method="post">
<h1>活动报名表</h1>
<hr/>
<table align="center">
<h2>${activity.actitle}</h2><br>
<input type="hidden" value="${activity.actitle}" name="actitle">
<P style="width: 300px;">${activity.accontext}</P>
时间<br>
${activity.actime}<br>
<input type="hidden" value="${activity.actime}" name="actime">
地点<Br>
${activity.acplace}<br>
<input type="hidden" value="${activity.acplace}" name="acplace">
费用<Br>
${activity.accost}元<br>
<input type="hidden" value="${activity.accost}" name="accost">
</table>
<input type="hidden" value="${activity.acid}" name="jacid">
<input type="hidden" value="${userInfo.uid}" name="juid">
<hr>
<p> 昵称:${userInfo.uname}</p>
<input type="hidden" value="${userInfo.uname}" name="uname">
<P> 姓名: <input type="text" name="jname" id="jname" style="height: 26px;border:0px;border-bottom:#000000 1px solid;" required="required"></P>
<p> 电话: <input type="text" name="jphone" id="jphone" style="height: 26px;border:0px;border-bottom:#000000 1px solid;" required="required"></p>
<div style="margin-top:15px;">
<button type="submit" style="margin-bottom: 15px;color: black;">下载报名表</button>
</div>
</form>