天天看點

記錄-三步走FreeMarker Template學習

  學習Java模版引擎FreeMarker截至到現在20個小時,記錄一下整個學習過程,發現學習中的問題,同時留下對FreeMarker最初時的認知,待假以時日項目組的資料和視圖層分離使用FreeMarker的時侯不至于因為時間長了不知從何開始,又要重新走一步Hello FreeMarker的過程,又能夠溫故知新發現更多,更奇妙的東西。

記錄-三步走FreeMarker Template學習

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

  • 建立一個web工程,将freemarker.jar放置lib(classpath)目錄
  • 配置web.xml檔案,配置方式和普通的Servlet配置相同
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44

<

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的幫助文檔中寫的很清楚。

記錄-三步走FreeMarker Template學習
  • 建立一個test1.html模版内容如下:
1

<

div

><#assign v="hello freemarker"> ${v}</

div

>

  • 部署web工程打開test1.html
    記錄-三步走FreeMarker Template學習
  • OK,模版就是這麼搞定,關于更多的指令等資訊有第二步的博文,也有第三步的官方清晰可讀的文檔。

    下面是在探索中的一些總結:

  • FreeMarker資料模型+模版==輸入内容,可産生友好的表現
  • 資料模型有簡單資料類型,Sequence類型(Java的List,Array),Hasher類型(Map, Bean等),總體概況資料模型是一棵樹,保證資料以樹的形式組織,進而就有個root的概念
  • 實際使用過程中遇到的問題有很好的頁面異常資訊顯示,并仔細閱讀文檔都可以解決,注意留心每一個條目說明後的Note資訊
  • 特性豐富:内置的特性strings,numbers,booleans,dates等;指令特性聲明,導入,包含,循環,判斷,分支,功能函數,表達式等高頻率使用
  • 最後一條,學習一個沒有接觸過的東西,還是從Hello XX開始是一個良好的起端,另外與其在網上找各種文章,代碼段學習不如試試這三步,末了看看官方文檔初學遇到的問題基本都有清晰的說明并且能夠發現更多的東西。
記錄-三步走FreeMarker Template學習

一個例子說明官方文檔的優越性

   問題:自定義方法模型

   解決:官方文檔中有TemplateMethodModel接口配合源代碼模仿一個判斷字元串A是否包含字元串B的方法

   源碼:

   接口TemplateMethodModel繼承TemplateModel接口;

   接口TemplateMethodModelEx繼承了TemplateMethodModel接口;

   TemplateMethodModelEx接口的實作中有一個類是:SimpleMethodModel看看他的源碼就豁然開朗知道如何去實作我們自己的SimpleMethodIsContainsModel類。

   類:

1 2 3 4

public

final

class

SimpleMethodModel 

extends

SimpleMemberModel

implements

TemplateMethodModelEx,

TemplateSequenceModel

   核心實作方法:

1

public

Object exec(List arguments)

   自己實作:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

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(

)).contains((CharSequence) arguments

.get(

1

));

}

}

    用法測試:

    編寫一個servlet和一個模版

    1.Servlet實作

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44

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依賴一個工具助手類

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

package

com.broncho.fm;

import

javax.servlet.ServletContext;

import

freemarker.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.模版

1 2 3 4 5 6

<

div

>

<#assign arg1="tomcat" arg2="cat">

${arg1} is contains ${arg2}

<

br

/>

${iscontains(arg1, arg2)}

</

div

>

    說明:root很重要,建立的SimpleMethodIsContainsModel對象要作為方法使用,而在模版在的方法名就是root這個hasher的key值。

    3.部署運作

記錄-三步走FreeMarker Template學習

   運作之後報一大堆錯誤,摘取前部分重點資訊,可以看出模版中的部分資訊輸出,計算後的結果沒有輸出。

   上面這段異常提示資訊的資訊量足夠大,這也是個人感覺FreeMarker很牛的一點。

   分析:

  • isContains方法的傳回值是boolean類型,FreeMarker template不具備boolean自動轉string;
  • 不能轉還不能說FreeMarker template能力不行,接下來他給的解釋說 boolean_format設定為true,false,恰好這是他預設的計算語言格式,這麼一說就不能怪他了;
  • 還沒完,他給了兩個處理建議,一個是解決目前問題,另一個是解決此類轉換的方法,更人性化的是他還給了如何寫的例子,如:${myboolean?string('yes','no');
  • 至此,還有驚喜的是FreeMarker Template異常提示的位置相當精确,而且還具備從哪裡開始錯就在哪那裡開始報的優秀品質。

  修改後的模版資訊:

1 2 3 4 5 6

<

div

>

<#assign arg1="tomcat" arg2="cat">

${arg1} is contains ${arg2}

<

br

/>

${iscontains(arg1, arg2)?string("true","false")}

</

div

>

   末尾:實際上官方的幫助文檔這一點寫的很清楚,唯一要做的是習慣讀英文資料。

本文轉自 secondriver 51CTO部落格,原文連結:http://blog.51cto.com/aiilive/1332579,如需轉載請自行聯系原作者