生活随笔
收集整理的這篇文章主要介紹了
Java项目中使用Freemarker生成Word文档
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Web項目中生成Word文檔的操作屢見不鮮,基于Java的解決方案也是很多的,包括使用Jacob、Apache POI、Java2Word、iText等各種方式,其實在從Office 2003開始,就可以將Office文檔轉換成XML文件,這樣只要將需要填入的內容放上${}占位符,就可以使用像Freemarker這樣的模板引擎將出現占位符的地方替換成真實數據,這種方式較之其他的方案要更為簡單。
下面舉一個簡單的例子,比如在Web頁面中填寫個人簡歷,然后點擊保存下載到本地,效果圖如下所示。
打開下載的Word文件
首先在Eclipse?Java EE版中新建一個Dynamic Web Project,項目結構如下圖所示
需要向項目中加入freemarker的JAR文件,可以通過下面的鏈接獲得Freemarker的最新版本:
http://freemarker.org/freemarkerdownload.html
模板文件resume.ftl是如何生成的呢,其實非常簡單,將需要的Word文檔做好之后,選擇另存為XML文件,另存之后建議用Editplus、Notepad++、Sublime等工具打開查看一下,因為有的時候你寫的占位符可能會被拆開,這樣Freemarker就無法處理了。
打開XML文件看看吧,如果剛才你寫的${title}、${name}被xml文件給拆散了,修改一下XML文件就OK了。
修改過后另存為resume.ftl模板文件,如下所示:
接下來就是Servlet(也可以是Struts2的Action、spring?MVC的Controller等)和工具類WordGenerator的編寫以及頁面test.jsp的制作了,代碼如下所示:
小服務的代碼:
[java]? view plain copy
package?com.lovo.servlet;?? ?? import?java.io.File;?? import?java.io.FileInputStream;?? import?java.io.IOException;?? import?java.io.InputStream;?? import?java.util.Enumeration;?? import?java.util.HashMap;?? import?java.util.Map;?? ?? import?javax.servlet.ServletException;?? import?javax.servlet.ServletOutputStream;?? import?javax.servlet.annotation.WebServlet;?? import?javax.servlet.http.HttpServlet;?? import?javax.servlet.http.HttpServletRequest;?? import?javax.servlet.http.HttpServletResponse;?? ?? import?com.lovo.util.WordGenerator;?? ?? ? ? ?? @WebServlet("/saveDocServlet")?? public?class?MyServlet?extends?HttpServlet?{?? ????private?static?final?long?serialVersionUID?=?1L;?? ?? ????@Override?? ????protected?void?service(HttpServletRequest?req,?HttpServletResponse?resp)?? ????????????throws?ServletException,?IOException?{?? ????????req.setCharacterEncoding("utf-8");?? ????????Map<String,?Object>?map?=?new?HashMap<String,?Object>();?? ????????Enumeration<String>?paramNames?=?req.getParameterNames();?? ?????????? ????????while(paramNames.hasMoreElements())?{?? ????????????String?key?=?paramNames.nextElement();?? ????????????String?value?=?req.getParameter(key);?? ????????????map.put(key,?value);?? ????????}?? ?????? ?????????? ?????????? ????????File?file?=?null;?? ????????InputStream?fin?=?null;?? ????????ServletOutputStream?out?=?null;?? ????????try?{?? ?????????????? ????????????file?=?WordGenerator.createDoc(map,?"resume");?? ????????????fin?=?new?FileInputStream(file);?? ?????????????? ????????????resp.setCharacterEncoding("utf-8");?? ????????????resp.setContentType("application/msword");?? ?????????????? ????????????resp.addHeader("Content-Disposition",?"attachment;filename=resume.doc");?? ?????????????? ????????????out?=?resp.getOutputStream();?? ????????????byte[]?buffer?=?new?byte[512];???? ????????????int?bytesToRead?=?-1;?? ?????????????? ????????????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();??? ????????}?? ????}?? ?? }??
工具類的代碼:
[java]? view plain copy
package?com.lovo.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,?"/com/lovo/ftl");?? ????????allTemplates?=?new?HashMap<>();????? ????????try?{?? ????????????allTemplates.put("resume",?configuration.getTemplate("resume.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?{?? ?????????????? ????????????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;?? ????}?? ?? }??
JSP頁面的代碼:
[html]? view plain copy
<%@?page?pageEncoding="UTF-8"%>?? <!DOCTYPE?html>?? <html>?? <head>?? <meta?charset="UTF-8"?/>?? <title>Document</title>?? <style?type="text/css">?? ????*?{?font-family:?"微軟雅黑";?}?? ????.textField?{?border:none;?border-bottom:?1px?solid?gray;?text-align:?center;?}?? ????#file?{?border:1px?solid?black;?width:?80%;?margin:0?auto;?}?? ????h1?input{?font-size:72px;?}?? ????td?textarea?{?font-size:?14px;?}?? ????.key?{?width:125px;?font-size:20px;?}?? </style>?? </head>?? <body>?? ????<form?action="saveDocServlet"?method="post">?? ????<div?id="file"?align="center">?? ????????<h1><input?type="text"?name="title"?class="textField"?value="我的簡歷"/></h1>?? ????????<hr/>?? ????????<table>?? ????????????<tr>?? ????????????????<td?class="key">姓名:</td>?? ????????????????<td><input?type="text"?name="name"?class="textField"/></td>?? ????????????????<td?class="key">性別:</td>?? ????????????????<td>?? ????????????????????<input?type="radio"?name="gender"?value="男"?checked/>男?? ????????????????????<input?type="radio"?name="gender"?value="女"?/>女?? ????????????????</td>?? ????????????</tr>?? ????????????<tr>?? ????????????????<td?class="key">聯系電話:</td>?? ????????????????<td><input?type="text"?name="tel"?class="textField"/></td>?? ????????????????<td?class="key">家庭住址:</td>?? ????????????????<td><input?type="text"?name="address"?class="textField"/></td>?? ????????????</tr>?? ????????????<tr>?? ????????????????<td?colspan="4"?class="key">個人簡介:</td>?? ????????????</tr>?? ????????????<tr>?? ????????????????<td?colspan="4">?? ????????????????????<textarea?rows="10"?cols="100"?name="content"></textarea>?? ????????????????</td>?? ????????????</tr>?? ????????</table>?? ????</div>?? ????<div?align="center"?style="margin-top:15px;">?? ????????<input?type="submit"?value="保存Word文檔"?/>?? ????</div>?? ????</form>?? </body>?? </html>??
說明:小服務是使用注解進行配置的,因此你的服務器需要支持Servlet 3規范,我使用的服務器是Tomcat 7.0.52。如果你的服務器不支持Servlet 3規范那就使用web.xml來配置你的小服務吧,其他地方沒有不同。如果你不熟悉Servlet 3規范的新特性,可以閱讀CSDN上另一篇文章,鏈接如下所示:
http://blog.csdn.net/zhongweijian/article/details/8279650
此外,如果你希望在Word文檔中插入圖片,可以把Word另存為的XML文件中代表圖片的那個很長的字符串(BASE64編碼的字符串)換成一個占位符,在將要插入Word文檔的圖片對象轉換成BASE64編碼的字符串,用該字符串替換掉占位符就可以了,示意圖和代碼如下所示:
將圖片轉換成BASE64字符串的代碼如下所示:
[java]? view plain copy
public?static?String?getImageString(String?filename)?throws?IOException?{?? ?????????InputStream?in?=?null;?? ?????????byte[]?data?=?null;?? ?????????try?{?? ?????????????in?=?new?FileInputStream(filename);?? ?????????????data?=?new?byte[in.available()];?? ?????????????in.read(data);?? ?????????????in.close();?? ?????????}?catch?(IOException?e)?{?? ?????????????throw?e;?? ?????????}?finally?{?? ?????????????if(in?!=?null)?in.close();?? ?????????}?? ?????????BASE64Encoder?encoder?=?new?BASE64Encoder();?? ?????????return?data?!=?null???encoder.encode(data)?:?"";?? ????}??
注意:這里使用的BASE64Encoder類在sun.misc包下,rt.jar中有這個類,但是卻無法直接使用,需要修改訪問權限,在Eclipse中可以這樣修改。
在項目上點右鍵選擇Properties菜單項進入如下圖所示的界面:
這樣設置后就可以使用BASE64Encoder類了,在項目中調用getImageString方法指定要插入的圖片的完整文件名(帶路徑的文件名),該方法返回的字符串就是將圖片處理成BASE64編碼后的字符串。
總結
以上是生活随笔為你收集整理的Java项目中使用Freemarker生成Word文档的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。