005_FreeMarker入门程序
一. 創建Configuration實例
1. 使用FreeMarker, 首先, 你應該創建一個freemarker.template.Configuration實例, 然后調整它的設置。Configuration實例是存儲FreeMarker應用級設置的核心部分。同時, 它也處理創建和緩存預解析模板(比如: Template對象)的工作。
2. 不需要重復創建Configuration實例; 它的代價很高, 尤其是會丟失緩存。Configuration實例就是應用級別的單例。
3. 當使用多線程應用程序(比如Web網站), Configuration實例中的設置就不能被修改。它們可以被視作為"有效的不可改變的"對象, 也可以使用線程安全技術來保證實例對其它線程也可用。
二. 創建數據模型
1. 在簡單的示例中你可以使用java.lang和java.util包中的類, 還有用戶自定義的Java Bean來構建數據對象:
1.1. 使用java.lang.String來構建字符串。
1.2. 使用java.lang.Number來派生數字類型。
1.3. 使用java.lang.Boolean來構建布爾值。
1.4. 使用java.util.List或Java數組來構建序列。
1.5. 使用java.util.Map來構建哈希表。
1.6. 使用自定義的bean類來構建哈希表, bean中的項和bean的屬性對應。比如: product的price屬性(getProperty())可以通過product.price獲取。
2. 下面是構建這個數據模型的Java代碼片段:
Map<String, Object> root = new HashMap<String, Object>(); List<String> colors = new ArrayList<String>(); colors.add("陶瓷黑"); colors.add("陶瓷白"); root.put("colors", colors); root.put("id", 100001); root.put("name", "HUAWEI Mate 40 RS 保時捷設計"); root.put("price", 12999.00F); root.put("date", new Date(System.currentTimeMillis())); root.put("fastCharge", true);3. 在真實應用系統中, 通常會使用應用程序指定的類來代替Map, 它會有JavaBean規范規定的getXxx/isXxx方法。比如有一個和下面類似的類:
public class Product {private Integer id; // 商品id...public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}... } List<String> colors = new ArrayList<String>(); colors.add("陶瓷黑"); colors.add("陶瓷白"); Product root = new Product(100002, "HUAWEI Mate 40 RS 保時捷設計", 12999.00F, colors, new Date(System.currentTimeMillis()), true);三. 獲取模板
1. 模板代表了freemarker.template.Template實例。典型的做法是從Configuration實例中獲取一個Template實例。無論什么時候你需要一個模板實例, 都可以使用它的getTemplate方法來獲取。假如我們獲取一個test.html模板, 那么就可以這樣來做:
Template temp = cfg.getTemplate("test.html");
2. 當調用這個方法的時候, 將會創建一個test.html的Template實例, 通過讀取/where/you/store/templates/test.html文件, 之后解析(編譯)它。Template實例以解析后的形式存儲模板, 而不是以源文件的文本形式。
3. Configuration緩存Template實例, 當再次獲得test.html的時候, 它可能再讀取和解析模板文件了, 而只是返回第一次的Template實例。
四. 合并模板和數據模型
1. 我們已經知道, 數據模型+模板=輸出, 我們有了一個數據模型(root)和一個模板(temp), 為了得到輸出就需要合并它們。這是由模板的process方法完成的。它用數據模型root和Writer對象作為參數, 然后向Writer對象寫入產生的內容。為簡單起見, 這里我們只做標準的輸出:
Writer out = new OutputStreamWriter(System.out); temp.process(root, out);2. Java I/O相關注意事項: 基于out對象, 必須保證out.close()最后被調用。其它時候, 比如典型的Web應用程序, 那就不能關閉out對象。FreeMarker會在模板執行成功后(也可以在Configuration中禁用)調用out.flush(), 所以不必為此擔心。
3. 請注意, 一旦獲得了Template實例, 就能將它和不同的數據模型進行不限次數(Template實例是無狀態的)的合并。此外, 當Template實例創建之后test.html文件才能訪問, 而不是在調用處理方法時。
5. 例子
5.1. 新建一個名為FMRuMen動態Web工程, 同時添加相關jar包。
5.2. 編寫FMFactory.java
package com.fm.util;import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import freemarker.template.Configuration; import freemarker.template.TemplateExceptionHandler;public class FMFactory {private final static FMFactory instance = new FMFactory();private FMFactory() {}public static FMFactory getInstance() {return instance;}private Map<String, Configuration> map = new ConcurrentHashMap<String, Configuration>();// 創建單個Configuration實例public synchronized Configuration getCfg(Object servletContext, String path) {if(null != map.get(path)) {return map.get(path);}Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);cfg.setServletContextForTemplateLoading(servletContext, path);cfg.setDefaultEncoding("utf-8");cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);map.put(path, cfg);return cfg;}}5.3. 編寫Product.java
package com.fm.model;import java.io.Serializable; import java.sql.Date; import java.util.List;public class Product implements Serializable {private static final long serialVersionUID = 1L;private Integer id; // 商品idprivate String name; // 商品名稱private Float price; // 商品價格private List<String> colors; // 商品顏色private Date date; // 出廠日期private Boolean fastCharge; // 是否支持快充public Product() {}public Product(Integer id, String name, Float price, List<String> colors, Date date, Boolean fastCharge) {this.id = id;this.name = name;this.price = price;this.colors = colors;this.date = date;this.fastCharge = fastCharge;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Float getPrice() {return price;}public void setPrice(Float price) {this.price = price;}public List<String> getColors() {return colors;}public void setColors(List<String> colors) {this.colors = colors;}public Date getDate() {return date;}public void setDate(Date date) {this.date = date;}public Boolean getFastCharge() {return fastCharge;}public void setFastCharge(Boolean fastCharge) {this.fastCharge = fastCharge;}}5.4. 編寫ProductInfo.java
package com.fm.action;import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; import java.sql.Date; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.fm.model.Product; import com.fm.util.FMFactory; import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException;public class ProductInfo extends HttpServlet {private static final long serialVersionUID = 1L;@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {Configuration cfg = FMFactory.getInstance().getCfg(req.getServletContext(), "WEB-INF/templates/product");// Map<String, Object> root = new HashMap<>(); // List<String> colors = new ArrayList<String>(); // colors.add("陶瓷黑"); // colors.add("陶瓷白"); // root.put("colors", colors); // root.put("id", 100001); // root.put("name", "HUAWEI Mate 40 RS 保時捷設計"); // root.put("price", 12999.00F); // root.put("date", new Date(System.currentTimeMillis())); // root.put("fastCharge", true);// 創建數據模型List<String> colors = new ArrayList<String>();colors.add("陶瓷黑");colors.add("陶瓷白");Product root = new Product(100002, "HUAWEI Mate 40 RS 保時捷設計", 12999.00F, colors, new Date(System.currentTimeMillis()), true);// 獲取模板Template temp = cfg.getTemplate("product.html");Writer out = new OutputStreamWriter(resp.getOutputStream());try {// 合并模板和數據模型temp.process(root, out);} catch (TemplateException e) {e.printStackTrace();}}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);} }5.5. 編寫index.html
<!DOCTYPE html> <html><head><meta charset="UTF-8" /><title>主頁</title></head><body><a href="pi.action">商品信息</a></body> </html>5.6. 修改web.xml
5.7. 在WEB-INF/templates/product目錄下, 編寫product.html模板文件
<!DOCTYPE html> <html><head><meta charset="UTF-8" /><title>商品信息</title></head><body><!-- c(當用于布爾值時)該內建函數將布爾值轉換為字符串, 針對"計算機語言"而不是用戶。結果是"true"或"false"。c就代表計算機的意思。--><!-- c(當被用作是數字值時)該內建函數將"計算機語言"的數字轉換成字符串, 這都是對計算機來說的, 而不是對用戶。c就代表計算機的意思。 -->商品編號: ${id?c} <br />商品名字: ${name} <br />商品價格: ¥ ${price?c} <br />商品顏色: ${colors[0]}, ${colors[1]} <br />出廠日期: ${date} <br /><!-- 布爾類型需要轉換為字符串類型輸出 --><!-- booleanExp?then(whenTrue, whenFalse), 就像是類C語言中的三元運算符 -->支持快充: ${fastCharge?then("支持快充", "不支持快充")}</body> </html>5.8. 運行項目
5.9. 訪問商品信息
?
總結
以上是生活随笔為你收集整理的005_FreeMarker入门程序的全部內容,希望文章能夠幫你解決所遇到的問題。