FreeMarker模版引擎實現匯出world文件到本地

阿木俠發表於2017-05-26

http://freemarker.org/

Freemarker官網,英文,可以用谷歌瀏覽器的自動翻譯,英文水平高的忽略這句。。

簡單來說:FreeMarker是一個模板引擎,一個基於模板生成文字輸出的通用工具,使用純Java編寫。FreeMarker被設計用來生成HTMLWeb頁面,特別是基於MVC模式的應用程式。

這裡使用freemarker生成Word文件,非常方便。

慣例,先看看Demo整體結構:

Demo結構:


這裡要引入freemarker包,通過Freemarker載入word文件的模版

生成Word文件類ToCreateDoc

package org.javasun.createDoc;

import java.io.IOException;
import java.io.Writer;
import java.util.Map;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

public class ToCreateDoc {

	private Configuration configuration = null;

	public ToCreateDoc() {
		configuration = new Configuration();
		configuration.setDefaultEncoding("UTF-8");
	}

	public void createDoc(Writer out, Map<String, Object> dataMap, String ftlName) {
		configuration.setClassForTemplateLoading(getClass(), "/ftl");
		try {
		    	
			Template t = null;
			t = configuration.getTemplate(ftlName,"UTF-8");
			t.process(dataMap, out);
		} catch (TemplateException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

Servlet,填資料傳送客戶端處理:

package org.javasun.servlet;

import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.javasun.createDoc.ToCreateDoc;

@WebServlet("/download")
public class DownloadServlet extends HttpServlet {
	public DownloadServlet() {
		super();
	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 設定response型別
		String fileName = "test.doc";
		// 設定響應正文的MIME型別
		response.setCharacterEncoding("utf-8");
		response.setHeader("Content-Disposition", "attachment;" + " filename=" + fileName);
		// 獲取資料,設定資料
		Map<String, Object> dataMap = new HashMap<>();
		dataMap.put("company", "XXX百貨公司");
		dataMap.put("companyname", "XXX批發商");
		dataMap.put("addr", "太原市XXXX");
		dataMap.put("contact", "張文先生");
		dataMap.put("phone", "12345678");

		List<Map<String, String>> payList = new ArrayList<>();
		for (int i = 1; i < 8; i++) {
			Map<String, String> iMap = new HashMap<>();
			iMap.put("proName", "智慧手機" + i + "0");
			iMap.put("pay", i * 1000 + "");
			iMap.put("num", "105");
			iMap.put("total", "100333");
			payList.add(iMap);
		}

		dataMap.put("itemlist", payList);
		// 把本地檔案傳送給客戶端
		Writer out = response.getWriter();
		ToCreateDoc tcd = new ToCreateDoc();
		tcd.createDoc(out, dataMap, "demo.ftl");
		out.close();
	}
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}

}

Jsp頁面測試效果:

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title></title>
<script type="text/javascript">
	function download_file(url){		  
	    if (typeof (download_file.iframe) == "undefined")  
	    {  
	        var iframe = document.createElement("iframe");  
	        download_file.iframe = iframe;  
	        document.body.appendChild(download_file.iframe);  
	    }  
	    download_file.iframe.src = url;  
	    download_file.iframe.style.display = "none";
	}  
</script>
</head>
<body>
	<button onclick="download_file('download');" >單擊生成Word文件</button>
</body>
</html>

點選按鈕,Word文件就會自動下載,下載的檔案如圖:


我們可以看到,很方便,只要定義好檔案模版,就可以將資料庫資料匯入成文件格式儲存或者列印。

 

那麼如何定義模版呢?

將需要的Word文件做好之後(一般是沒有資料的一種文件模版格式),選擇另存為XML檔案,存為XML的目的是方便檢查,看看${}佔位符的內容是否被分開了(分開之後會導致很多問題,所以要調整格式,修改一下XML檔案),之後另存為.ftl模版檔案就OK了,在專案中引用就可以實現內容按所想的格式輸出。

 

如何引用?

Freemarker提供了3種載入模板目錄的方法。 它使用Configuration類載入模板

3種方法分別是:

public voidsetClassForTemplateLoading(Class clazz, String pathPrefix);

public voidsetDirectoryForTemplateLoading(File dir) throws IOException;

public voidsetServletContextForTemplateLoading(Object servletContext, String path);


分別基於類路徑、檔案系統以及Servlet Context路徑。

 

注意事項(匯出的Word文件很容易出現亂碼)如何解決?

我們在做模板匯出時需要注意以下三處編碼集的設定,有一處沒有設定就會導致到處uWord文件出現中文亂碼。

(1)configuration.setDefaultEncoding("UTF-8");

(2)Template t =configuration.getTemplate("模板檔案","UTF-8");

(3)Writer out = newBufferedWriter(new OutputStreamWriter(檔案輸出流 fos, "UTF-8"))。

 

 Demo下載地址:https://github.com/guodalin8/ToWordTest




相關文章