Freemarker常用技巧
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字符都需要用實體引用來代替(比如<代替<)
?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 & Jerry
TOM & 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></@greet>
如果沒有體內容也可以用
<@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{//得到函數第一個參數,得到的字符串兩頭會有引號,所以replaceString 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="首頁"><<</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="末頁">>></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常用技巧的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2008年第四季度开发者Top 100
- 下一篇: Canvas2~茜色的调色盘可奈线12月