日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java Web项目中使用Freemarker生成Word文档

發布時間:2024/3/13 java 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java Web项目中使用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 print ?
  • 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;??
  • ??
  • /**?
  • ?*?Servlet?implementation?class?MyServlet?
  • ?*/??
  • @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);??
  • ????????}??
  • ??????
  • ????????//?提示:在調用工具類生成Word文檔之前應當檢查所有字段是否完整??
  • ????????//?否則Freemarker的模板殷勤在處理時可能會因為找不到值而報錯?這里暫時忽略這個步驟了??
  • ????????File?file?=?null;??
  • ????????InputStream?fin?=?null;??
  • ????????ServletOutputStream?out?=?null;??
  • ????????try?{??
  • ????????????//?調用工具類WordGenerator的createDoc方法生成Word文檔??
  • ????????????file?=?WordGenerator.createDoc(map,?"resume");??
  • ????????????fin?=?new?FileInputStream(file);??
  • ??????????????
  • ????????????resp.setCharacterEncoding("utf-8");??
  • ????????????resp.setContentType("application/msword");??
  • ????????????//?設置瀏覽器以下載的方式處理該文件默認名為resume.doc??
  • ????????????resp.addHeader("Content-Disposition",?"attachment;filename=resume.doc");??
  • ??????????????
  • ????????????out?=?resp.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 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;/*** Servlet implementation class MyServlet*/ @WebServlet("/saveDocServlet") public class MyServlet extends HttpServlet {private static final long serialVersionUID = 1L;@Overrideprotected 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);}// 提示:在調用工具類生成Word文檔之前應當檢查所有字段是否完整// 否則Freemarker的模板殷勤在處理時可能會因為找不到值而報錯 這里暫時忽略這個步驟了File file = null;InputStream fin = null;ServletOutputStream out = null;try {// 調用工具類WordGenerator的createDoc方法生成Word文檔file = WordGenerator.createDoc(map, "resume");fin = new FileInputStream(file);resp.setCharacterEncoding("utf-8");resp.setContentType("application/msword");// 設置瀏覽器以下載的方式處理該文件默認名為resume.docresp.addHeader("Content-Disposition", "attachment;filename=resume.doc");out = resp.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(); // 刪除臨時文件}}}

    工具類的代碼:

    [java] view plain copy print ?
  • 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<>();???//?Java?7?鉆石語法??
  • ????????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?{??
  • ????????????//?這個地方不能使用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;??
  • ????}??
  • ??
  • }??
  • 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<>(); // Java 7 鉆石語法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 {// 這個地方不能使用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;}}

    JSP頁面的代碼:

    [html] view plain copy print ?
  • <%@?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>??
  • <%@ 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 print ?
  • 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)?:?"";??
  • ????}??
  • 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 Web项目中使用Freemarker生成Word文档的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。