1. 程式人生 > >Freemarker 常用指南(收藏)

Freemarker 常用指南(收藏)

其他 win pattern assign .gz 視圖 href in子句 可能

1,截取字符串

有的時候我們在頁面中不需要顯示那麽長的字符串,比如新聞標題,這樣用下面的例子就可以自定義顯示的長度

< lt. <= lte. > gt. >= gte

<#if jstbqkVO.gzdd?length lt 8>
<a href>${jstbqkVO.gzdd?default("")}</a>
<#else>
<a href title="${jstbqkVO.gzdd}">${jstbqkVO.gzdd[0..3]?default("")}...</a>
</#if>

意思就是如果這個字符串的長度小於8,那麽就正常顯示,反之則取4位

2.連接字符串

${"Hello," + user + "!"} //輸出結果為:hello,gs!

3,日期格式和boolean 類型,轉化為string類型

例子2:

${lastUpdate?string("yyyy-MM-dd HH:mm:ss zzzz")}

${lastUpdate?string("EEE,MMM d, ‘‘yy")}

${.................("EEEE,MMM dd,yyyy, hh:mm:ss a ‘(‘zzz‘)‘")}

輸出結果如下:

2003-04-08 21:24:44 Pacific Daylight Time

Tue,Apr 8,‘03

Tuesday,April 08,2003,09:24:44 PM (PDT)

例子3:

<#assign foo=true/>

${foo?string("yes","no")} //輸出結果:yes

4,排序:

1.升序.sort_by()

<#list list?sort_by("字段") as x>
</#list>

2.降序.sort_by()?reverse

<#list list?sort_by("字段")?reverse as x>
</#list>

5去空格:

${xx?trim}

6數值精度控制

mX:小數部分最小X位。

MX:小數部分最大X位。

例子:

<#assign x=2.582/>

<#assign y=4/>

#{x; M2} //2.58

#{y; M2} //4

#{x; m1M2} //2.58

#{y; m1M2} //4.0

7特殊字符串的轉義

\":雙引號 \\:反斜杠 \r:回車 \b:退格鍵

\‘:單引號 \n:換行 \t:Tab \f:Form feed

\l:< \g:> \a:& \{:{

\xCode:直接通過4位的十六進制數來指定Unicode碼

,輸出改Unicode對應的字符。

8.頂層變量

* 所謂頂層變量就是直接放在數據模型中的值。

Map root = new HashMap();

root.put("name","yeeku"); //name是一個頂層對象

* 對於頂層變量,直接使用${variableName}來輸出變量值

9.集合連接運算符

* 集合連接運算是將兩個集合連接成一個新的集合,連接集合的運算符是‘+‘.

<#list ["一","二","三"] + ["四","五","六"] as x>

${x}

</#list>

//輸出結果如下:

一二三四五六

10 算術運算符

* 取整運算

<#assign x=5>

${(x/2)?>int} //2

${1.1?int} //1

${1.999?int} //1

${-1.1?int} //-1

11 比較運算符

=(==) :判斷兩個值是否相等

!= :............不相等

>(gt) :判斷左邊是否大於右邊

>=(gte) :.....

<(lt) :.....

<=(lte) :.....

12 邏輯運算符

* 邏輯運算符只能作用於布爾值,否則將產生錯誤.

邏輯與:&&

邏輯或:||

邏輯非:!

13 內置函數

html:字符串中所有的特殊HTML字符都需要用實體引用來代替(比如<代替&lt;)
cap_first:字符串的第一個字母變為大寫形式
lower_case:字符串的小寫形式
upper_case:字符串的大寫形式
trim:去掉字符串首尾的空格

序列使用的內建函數:
size:序列中元素的個數
數字使用的內建函數:
int:數字的整數部分(比如-1.9?int就是-1)9>.空值運算符

length:字符串的長度

string :把其他格式的數據,轉化為string類型

例:

${test?html}
${test?upper_case?html}

假設字符串test存儲”Tom & Jerry”,那麽輸出為:

Tom &amp; Jerry
TOM &amp; JERRY

${seasons?size}
${seasons[1]?cap_first}

${"horse"?cap_first}

假設seasons存儲了序列"winter", "spring", "summer", "autumn",那麽上面的輸出將會是:

4
Spring
Horse

14.運算符優先級

* 推薦使用括號來決定運算優先級.

1>.一元運算符: !

2>.內建函數 : ?

3>.乘除法 : *,/,%

4>.加減法 : +,-

5>.比較 : <,>,<=,>=(lt,lte,gt,gte)

6>.相等 : ==(=),!=

7>.邏輯與 : &&

8>.邏輯或 : ||

9>.數字範圍 : ..

15,freemarker判斷返回值是否為空,null的方法

對於null,或者miss value,freemarker會報錯
!:default value operator,語法結構為:unsafe_expr!default_expr,比如 ${mouse!"No mouse."} 當mouse不存在時,返回default value;
(product.color)!"red" 這種方式,能夠處理product或者color為miss value的情況;
而product.color!"red"將只處理color為miss value的情況
??: Missing value test operator ,測試是否為missing value
unsafe_expr?? :product.color??將只測試color是否為null
(unsafe_expr)??:(product.color)??將測試product和color是否存在null
?exists:舊版本的用法
比如:<#if mouse??>
Mouse found
<#else>
No mouse found
</#if>
Creating mouse...
<#assign mouse = "Jerry">
<#if mouse??>
Mouse found
<#else>
No mouse found
</#if>

FreeMarker的常用指令

1>.if指令

<#if condifition>

...

<#elseif condifition>

...

<#else>

...

</#if>

2>.switch、case、default、break指令

<#switch value>

<#case refValue1>

...

<#break>

<#case refValue2>

...

<#break>

<#default>

...

</#switch>

3>.list、break指令

<#list sequence as item>

...

</#list>

* item_index :當前變量的索引值.

* item_has_next :是否存在下一個對象.

例子:

<#list ["星期一","星期二","星期三","星期四","星期五","星期六"] as x>

${x_index + 1}.${x}

<#if x_has_next>,</#if>

<#if x="星期四"><#break></#if>

</#list>

輸出結果:

1.星期一,

2.星期二,

3.星期三,

4.興趣四,

4>.include指令

:用於指定包含指定頁面.

<#include filename [options]>

* filename: 該參數指定被包含的模板文件.

* options : 該參數可以被省略,指定包含時的選項,包含encoding和parase兩個選項.

5>.import指令

<#import path as mapObject>

* path :指定要被導入的模板文件.

* mapObject :是一個Map對象.

意思:將path路徑中的變量都放在mapObject中.

例子:<#import "/lib/common.ftl" as com>

6>.noparser指令

noparse指令指定FreeMarker不處理該指令裏包含的內容.

<#noparse>...</#noparse>

7>.escape指令

* escape:該指令導致body區的插值都會被自動加上escape表達式.

* escape指令解析模板時起作用,而不是在運行時起作用.

* escape指令也嵌套使用,子escape繼承父escape的規則.

* 如果需要指定某些插值無需添加escape表達式,則應該使用noescape指令.

<#escape identifier as expression>

...

<#noescape>...</#noescape>

...

</#escape>

8>.assign指令

* 它用於為該模板頁面創建或替換一個(頂層)或多個變量.

第一種用法:<#assign name="value" [in namespacehash]>

in子句用於將創建的name變量放入namespacehash命名空間中.

第二種用法:<#assign name1=value1 name2=value2 ... nameN=valueN [in namespacehash]>

第三種用法: 是指將assign指令的內容賦值給name變量.

<#assign name [in namespacehash]>

capture this

</#assign>

例子:

<#assign x>

<#list ["一","二","三"] as n>

${n}

</#list>

</#assign>

${x}

補充.global指令,全局變量賦值

9>.setting指令

:該指令用於設置FreeMarker的運行環境.

<#setting name=value>

name的取值範圍如下:

locale:該指令指定該模板所使用的國家語言/語言選項.

number_format:該指令指定格式化輸出數字的選項.

boolean_format:該指令指令兩個布爾值的語法格式,默認值是"false".

date_format、time_format、datetime_format:格式化輸出日期的格式.

time_zone: 設置格式化輸出日期時所使用的時區.

10>.macro、nested、return指令

宏和變換器變量是兩種不同類型的用戶自定義指令,他們的區別是:

宏可以在模板中用macro指令來定義
變換器是在模板外由程序定義

1、宏:和某個變量關聯的模板片段,以便在模板中通過用戶自定義指令使用該變量
1-1、基本用法:
例如:
<#macro greet>
<font size="+2"> Hello JOE!</font>
</#macro>


使用時:
<@greet><[email protected]>
如果沒有體內容也可以用
<@greet />

1-2、變量:

1)、可以在宏定義之後定義參數,宏參數是局部變量,只在宏定義中有效。如:

<#macro greet person>
<font size="+2"> Hello ${person}!</font>
</#macro>
使用時:
<@greet person="emma"> and <@greet person="LEO">
輸出為:
<font size="+2"> Hello emma!</font>
<font size="+2"> Hello LEO!</font>

註意:宏的參數是FTL表達式,所以,person=emma和上面的例子中具有不同的意義,這意味著將變量emma的值傳給person,這個值可能是任意一種數據類型,甚至是一個復雜的表達式。

宏可以有多個參數,使用時參數的次序是無關的,但是只能使用宏中定義的參數,並且對所有參數賦值。如:
<#macro greet person color>
<font size="+2" color="${color}"> Hello ${person}!</font>
</#macro>

使用時:
<@greet color="black" person="emma" />正確
<@greet person="emma" />錯誤,color沒有賦值,此時,如果在定義宏時為color定義缺省值<#macro greet person color="black">這樣的話,這個使用方法就是正確的。
<@greet color="black" person="emma" bgcolor="yellow" />錯誤,宏greet定義中未指定bgcolor這個參數

11>自定義函數的使用

. 編寫函數

  package com.freemarker.test;
 
  import java.text.SimpleDateFormat;
  import java.util.Date;
  import java.util.List;
  import freemarker.template.TemplateMethodModel;
  import freemarker.template.TemplateModelException;
 
  
 public class SqlGetSysdateMethod implements TemplateMethodModel
 {
 
     
     public Object exec( List args ) throws TemplateModelException
     {
                 //得到函數第一個參數,得到的字符串兩頭會有引號,所以replace
         String datePattern=(args.get( 0 ).toString()).replace( ,  );
         
         Date date = new Date();
         SimpleDateFormat sdf =new SimpleDateFormat(datePattern);
         
         return sdf.format( date );
     }

 }

2.註冊與使用

   有兩種方式:

   (1).在模板文件中註冊,在模板中使用

<#assign getSysdate= package com.freemarker.test.SqlGetSysdateMethod?new()>

<#assign curdate= getSysdate(yyyy-MM-ddt)/>
(2).處理模板文件時註冊關鍵代碼:

Map<String,Object> root=new HashMap<String, Object>();
root.put(getSysdate, new StringLengthMethod());
Configuration config=new Configuration();
File file=new File(templatePath);
//並加載模板文件
config.setDirectoryForTemplateLoading(file);
//設置包裝器,並將對象包裝為數據模型
config.setObjectWrapper(new DefaultObjectWrapper());

//獲取模板,並設置編碼方式,這個編碼必須要與頁面中的編碼格式一致
Template template=config.getTemplate(templateName,templateEncoding);
//合並數據模型與模板
template.process(root, out);

12>使用宏寫一個簡單的分頁實例

<#macro pagination totalCount pageSize>

<#--聲明一個函數transform 轉換uri,在新的uri上pager_offset參數 -->

<#assign transform = "util.TransformURI"?new()>

<#--聲明一個函數,得到當前頁碼-->

<#assign pagerOffset = "util.PagerOffset"?new()>

<#--聲明一個函數,根據傳入的totalCount,pageSize得到總頁數-->

<#assign pagerCount = "util.PageCount"?new()>

<#assign pageCount=pagerCount(totalCount,pageSize)>

<#--得到當前的URI和請求參數,得到當前的頁碼-->

<#if request.queryString?exists>

<#assign uri=request.requestURI+"?"+request.queryString>

<#assign pageIndex=pagerOffset(uri)>

<#assign new_uri=transform(uri)>

<#else>

<#assign uri=request.requestURI>

<#assign pageIndex=pagerOffset(uri)>

<#assign new_uri=transform(uri)>

</#if>

<#if (pageIndex>pageCount)>

<#assign pageIndex=pageCount>

</#if>

<#if (pageIndex>1)>

<a href="${new_uri+1}" title="首頁">&lt;&lt;</a>

</#if>

<#--如果前面頁數過多,顯示"..."-->

<#if (pageIndex>5)>

<#assign prevPages=pageIndex-9>

<#if prevPages lt 1>

<#assign prevPages=1>

</#if>

<#assign start=pageIndex-4>

<a href="${new_uri+prevPages}" title="向前5頁">...</a>

<#else>

<#assign start=1>

</#if>

<#-- 顯示當前頁附近的頁-->

<#assign end=pageIndex+4>

<#if (end>pageCount)>

<#assign end=pageCount>

</#if>

<#list start..end as index>

<#if pageIndex==index>

<b>${index}</b>

<#else>

<a href="${new_uri+index}">${index}</a>

</#if>

</#list>

<#--如果後面頁數過多,顯示"...":-->

<#if (end lt pageCount)>

<#assign endend=end+5>

<#if (end>pageCount)>

<#assign end=pageCount>

</#if>

<a href="${new_uri+end}" title="向後5頁">...</a>

</#if>

<#-- 顯示"下一頁":-->

<#if (pageIndex lt pageCount)>

<a href="${new_uri+pageCount}" title="末頁">&gt;&gt;</a>

</#if>

</#macro>

自定義了三個方法:

PageCount.Java

package util;

import java.util.List;

import freemarker.template.TemplateMethodModel;

import freemarker.template.TemplateModelException;

/**

* 根據傳入的參數,計算出所有的頁數

* @author legolas

*/

public class PageCount implements TemplateMethodModel {

@Override

public Object exec(List args) throws TemplateModelException {

Integer totalCount = 0;

Integer pageSize = 0;

try {

totalCount = Integer.parseInt((String) args.get(0));

pageSize = Integer.parseInt((String) args.get(1));

} catch (NumberFormatException e) {

throw new TemplateModelException("請輸入正確的總記錄數和頁面記錄數");

}

Integer pageCount = totalCount / pageSize

+ (totalCount % pageSize == 0 ? 0 : 1);

return pageCount;

}

}

TransformURI.java

package util;

import java.util.List;

import freemarker.template.TemplateMethodModel;

import freemarker.template.TemplateModelException;

/**

* 根據傳入的uri,在uri後面加上分頁參數

* @author legolas

*

*/

public class TransformURI implements TemplateMethodModel{

@Override

public Object exec(List args) throws TemplateModelException {

String uri = (String) args.get(0);

int n = uri.lastIndexOf("?");

if (n == -1) {

return uri + "?pager_offset=";

}

if (uri.lastIndexOf("?pager_offset") != -1) {

uri = uri.substring(0, uri.lastIndexOf("=") + 1);

return uri;

}

String queryString = uri.substring(n + 1, uri.length());

String suburi = uri.substring(0, n + 1);

String[] strings = queryString.split("&");

for (int i = 0; i < strings.length; i++) {

if (strings[i].startsWith("pager_offset")) {

continue;

}

suburi += strings[i];

suburi += "&pager_offset=";

}

return suburi;

}

}

PagerOffset.java

package util;

import java.util.List;

import freemarker.template.TemplateMethodModel;

import freemarker.template.TemplateModelException;

/**

* 得到當前的頁碼

* @author legolas

*

*/

public class PagerOffset implements TemplateMethodModel {

@Override

public Object exec(List args) throws TemplateModelException {

String uri = (String) args.get(0);

String[] string = uri.split("pager_offset=");

if (string.length == 1) {

return 1;

} else {

Integer pager_offset = 1;

try {

pager_offset = Integer.parseInt(string[1]);

} catch (NumberFormatException e) {

pager_offset = 1;

}

return pager_offset;

}

}

}

7>.關於在FreeMarker中使用Struts2標簽

* FreeMarker作為視圖組件是由Servlet負責加載該模板,並使用數據模型填充該模板,並且將填充後

的標準HTML響應輸出給瀏覽者.

* 在Struts2框架的支持下,Struts2框架充當了之前的Servlet角色.

* 為了使所有的用戶請求都經過Struts2框架處理,我們將所有的FreeMarker模板放在WEB-INF/ftl路徑下.

* 放在WEB-INF/路徑下可以提供更好的安全性,因為Web容器會保證瀏覽者無法訪問到WEB-INF/路徑下的資源.

8>.解析模板中的變量

* Struts2解析FreeMarker模板中變量的順序如下:

1>.FreeMarker模板內建的變量

2>.ValueStack中的變量.

3>.ActionContext中的變量.

4>.HttpServletRequest範圍的屬性.

5>.HttpSession範圍的屬性.

6>.ServletContext範圍的屬性.

* FreeMarker模板的內建變量如下:

stack:代表ValueStack本身,可這樣訪問其中變量:${stack.findString(‘ognl expr‘)}

action:代表剛剛執行過的Action實例.

response:代表HttpServletResponse實例.

request:代表HttpServletRequest實例.

res:代表HttpServletRequest實例.

session:代表HttpSession實例.

application:代表ServletContext實例.

base:代表用戶請求的上下文路徑.

9>.訪問Servlet/JSp範圍對象

1.訪問Application範圍內的屬性.

<#if Application.attributeName?exists>

${Application.attributeName}

</#if>

使用struts2標簽輸出:<@s.property value="%{Application.attributeName}"/>

2.訪問HttpServletRequest中的參數

<#if Parameter.parameter?exists>

${Parameter.parameter}

</#if>

Freemarker 常用指南(收藏)