學習Java模版引擎FreeMarker截至到現在20個小時,記錄一下整個學習過程,發現學習中的問題,同時留下對FreeMarker最初時的認知,待假以時日項目組的資料和視圖層分離使用FreeMarker的時侯不至於因為時間長了不知從何開始,又要重新走一步Hello FreeMarker的過程,又能夠溫故知新發現更多,更奇妙的東西。
650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131229/1224092918-0.gif" alt="j_0001.gif" />Hello FreeMarker
1.百度百科:FreeMarker http://baike.baidu.com/link?url=204dZtLs4TQhVPp2V_gFfJrv9EzewLu3R4AXHOWIhr9CLxbgnxu0AewyWDmoxWhqGtNH0Dk9PlF-Wpd-rLPpwa
很牛,很強大,能做表現出,也能當工具使,Java語言編寫的模版引擎且對Web容器無與依賴性。
2.找一篇博文看看Iteye 曾Java著名社區
http://relive123-yahoo-com-cn.iteye.com/blog/818013
基本瞭解FreeMarker基本寫法,功能特性,怎麼弄個Hello FreeMarker出來
3.出自何門何派,官方網站走一圈
http://freemarker.org/index.html
驚喜,有部分中文文檔,竊喜,英文文檔也很清晰可讀。
4.嘗試我的Hello FreeMarker
<servlet> <servlet-name>freemarker</servlet-name> <servlet-class>freemarker.ext.servlet.FreemarkerServlet</servlet-class> <init-param> <param-name>TemplatePath</param-name> <param-value>/</param-value> </init-param> <init-param> <param-name>NoCache</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>ContentType</param-name> <param-value>text/html</param-value> </init-param> <init-param> <param-name>template_update_delay</param-name> <param-value>0</param-value> </init-param> <init-param> <param-name>locale</param-name> <param-value>zh_CN</param-value> </init-param> <init-param> <param-name>default_encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>output_encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>date_format</param-name> <param-value>yyyy-MM-dd</param-value> </init-param> <init-param> <param-name>time_format</param-name> <param-value>HH:mm:ss</param-value> </init-param> <init-param> <param-name>datetime_format</param-name> <param-value>yyyy-MM-dd HH:mm:ss</param-value> </init-param> </servlet>
注意:初始化的參數很多可以根據需要配置,或者在使用的時候在進行設定,在FreeMarker的協助文檔中寫的很清楚。
650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131229/12240aR3-1.png" style="float:none;" title="freemarker-setting.png" alt="195238806.png" />
<div><#assign v="hello freemarker"> ${v}</div>
部署web工程開啟test1.html
650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131229/1224092462-2.png" title="QQ拼音未命名.png" alt="195551374.png" />
OK,模版就是這麼搞定,關於更多的指令等資訊有第二步的博文,也有第三步的官方清晰可讀的文檔。
下面是在探索中的一些總結:
FreeMarker資料模型+模版==輸入內容,可產生友好的表現
資料模型有單一資料型別,Sequence類型Java的List,Array),Hasher類型Map, Bean等),總體概況資料模型是一棵樹,保證資料以樹的形式組織,從而就有個root的概念
實際使用過程中遇到的問題有很好的頁面異常資訊顯示,並仔細閱讀文檔都可以解決,注意留心每一個條目說明後的Note資訊
特性豐富:內建的特性strings,numbers,booleans,dates等;指令特性聲明,匯入,包含,迴圈,判斷,分支,功能函數,運算式等高頻率使用
最後一條,學習一個沒有接觸過的東西,還是從Hello XX開始是一個良好的起端,另外與其在網上找各種文章,程式碼片段學習不如試試這三步,末了看看官方文檔初學遇到的問題基本都有清晰的說明並且能夠發現更多的東西。
650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131229/1224092918-0.gif" alt="j_0001.gif" />一個例子說明官方文檔的優越性
問題:自訂方法模型
解決:官方文檔中有TemplateMethodModel介面配合原始碼模仿一個判斷字串A是否包含字串B的方法
源碼:
介面TemplateMethodModel繼承TemplateModel介面;
介面TemplateMethodModelEx繼承了TemplateMethodModel介面;
TemplateMethodModelEx介面的實現中有一個類是:SimpleMethodModel看看他的源碼就豁然開朗知道如何去實現我們自己的SimpleMethodIsContainsModel類。
類:
public final class SimpleMethodModel extends SimpleMemberModel implements TemplateMethodModelEx, TemplateSequenceModel
核心實現方法:
public Object exec(List arguments)
自己實現:
package com.broncho.fm;import java.util.List;import freemarker.template.TemplateMethodModel;import freemarker.template.TemplateModelException;@SuppressWarnings("deprecation")public class SimpleMethodIsContainsModel implements TemplateMethodModel { @Override public Object exec(List arguments) throws TemplateModelException { if (arguments.size() != 2) { throw new TemplateModelException( "template model arguments is wrong !"); } return ((String) arguments.get(0)).contains((CharSequence) arguments .get(1)); }}
用法測試:
編寫一個servlet和一個模版
1.Servlet實現
package com.broncho.fm;import java.io.IOException;import java.util.HashMap;import java.util.Map;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import freemarker.template.Template;import freemarker.template.TemplateException;public class TestMethodServlet extends HttpServlet { private static final long serialVersionUID = -8862621014491094117L; private Template template; public TestMethodServlet() { super(); } public void destroy() { super.destroy(); } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); response.setCharacterEncoding("UTF-8"); Map<String, SimpleMethodIsContainsModel> root = new HashMap<String, SimpleMethodIsContainsModel>(); root.put("iscontains", new SimpleMethodIsContainsModel()); try { template.process(root, response.getWriter()); } catch (TemplateException e) { e.printStackTrace(); } } public void init() throws ServletException { try { template = FreeMarkerTemplateFactory.getConfiguration( this.getServletContext(), "/").getTemplate("block2.ftl"); } catch (IOException e) { e.printStackTrace(); } }}
這裡servlet依賴一個工具助手類
package com.broncho.fm;import javax.servlet.ServletContext;import freemarker.template.Configuration;/** * Template Configuration * */public class FreeMarkerTemplateFactory { public static Configuration cfg; public static void init() { if (cfg == null) { cfg = new Configuration(); } } public static Configuration getConfiguration(ServletContext servletContext, String path) { init(); if (path == null) { path = "/"; } cfg.setServletContextForTemplateLoading(servletContext, path); return cfg; }}
2.模版
<div> <#assign arg1="tomcat" arg2="cat"> ${arg1} is contains ${arg2} <br/> ${iscontains(arg1, arg2)} </div>
說明:root很重要,建立的SimpleMethodIsContainsModel對象要作為方法使用,而在模版在的方法名就是root這個hasher的key值。
3.部署運行
650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131229/12240a363-4.png" title="boolean.png" alt="203943988.png" />
運行之後報一大堆錯誤,摘取前部分重點資訊,可以看出模版中的部分資訊輸出,計算後的結果沒有輸出。
上面這段異常提示資訊的資訊量足夠大,這也是個人感覺FreeMarker很牛的一點。
分析:
isContains方法的傳回值是boolean類型,FreeMarker template不具備boolean自動轉string;
不能轉還不能說FreeMarker template能力不行,接下來他給的解釋說 boolean_format設定為true,false,恰好這是他預設的計算語言格式,這麼一說就不能怪他了;
還沒完,他給了兩個處理建議,一個是解決當前問題,另一個是解決此類轉換的方法,更人性化的是他還給了如何寫的例子,如:${myboolean?string('yes','no');
至此,還有驚喜的是FreeMarker Template異常提示的位置相當精確,而且還具備從哪裡開始錯就在哪那裡開始報的優秀品質。
修改後的模版資訊:
<div> <#assign arg1="tomcat" arg2="cat"> ${arg1} is contains ${arg2} <br/> ${iscontains(arg1, arg2)?string("true","false")} </div>
末尾:實際上官方的協助文檔這一點寫的很清楚,唯一要做的是習慣讀英文資料。
本文出自 “野馬紅塵” 部落格,謝絕轉載!