Freemarker經常使用技巧(二)

1 list、break指令
<#list sequence as item>
  ...
</#list>
tem_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.興趣四,python


2 import指令
<#import path as mapObject>
path:指定要被導入的模板文件.
mapObject:是一個Map對象.
意思:將path路徑中的變量都放在mapObject中.
例子:<#import "/lib/common.ftl" as com>面試


3 宏的基本用法
例如:
<#macro greet>
<font size="+2"> Hello JOE!</font>
</#macro>
使用時:
<@greet></@greet>
若是沒有體內容也能夠用
<@greet />
能夠在宏定義以後定義參數,宏參數是局部變量,只在宏定義中有效。如:
<#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">這樣的話,這個使用方法就是正確的。緩存

 

FreeMarker緩存處理

上週我面試了一我的,無心中我問了一個問題:freemarker加載模板文件的緩存策略是什麼呢?很遺憾,面試者沒有回答出來。後來,我告訴面試者,學習一個框架,不只僅是要明白這個框架如何使用,還要了解一下框架的底層實現。本文主要是給你們說一下FreeMarker的緩存實現部分。本文的內容大部分來自於互聯網,要想更深刻的瞭解與掌握
FreeMarker緩存處理,我我的以爲仍是要深刻研讀源碼,而後再看看網上的分析以加深印象,這樣的學習效果是最好的。
FreeMarker 的緩存處理主要用於模版文件的緩存,通常來說,模版文件改動不會很頻繁,在一個流量很是大的網站中,若是頻繁的讀取模版文件對系統的負擔仍是很重的,所以 FreeMarker 經過將模版文件的內容進行緩存,來下降模版文件讀取的頻次,下降系統的負載。
當處理某個模版時,FreeMarker直接從緩存中返回對應的 Template 對象,並有一個默認的機制來保證該模版對象是跟模版文件同步的。若是使用的時候 FreemarkerServlet 時,有一個配置項template_update_delay用來指定更新模版文件的間隔時間,至關於多長時間檢測一下是否有必要從新加載模版文件,0 表示每次都從新加載,不然爲多少毫秒鐘檢測一下模版是否更改。
FreeMarker定義了一個統一的緩存處理接口CacheStorage,默認的實現是 MruCacheStorage 最近最少使用的緩存策略。通常狀況下,不多須要對緩存進行擴展處理。您能夠經過下面的代碼指定最大緩存的模版數:app

其中第一個參數是最大的強引用對象數,第二個爲最大的弱引用對象數。這兩個值FreeMarker默認的是0和 Integer.MAX_VALUE,代表模版緩存數是無限的。框架

 

freemarker空值的處理

FreeMarker的變量必須賦值,不然就會拋出異常。而對於FreeMarker來講,null值和不存在的變量是徹底同樣的,由於FreeMarker沒法理解null值。FreeMarker提供兩個運算符來避免空值:
(1)!運算符:指定缺失變量的默認值;
(2)??運算符:判斷變量是否存在。
!運算符有兩種用法:variable!或variable!defaultValue。第一種用法不給變量指定默認值,代表默認值是空字符串、長度爲0的集合、或長度爲0的Map對象。
注意:使用!運算符指定默認值並不要求默認值的類型和變量類型相同。下面是一個小例子:
<#-- ${sss}沒有定義這個變量,會報異常!-->
${sss!} <#--沒有定義這個變量,默認值是空字符串!-->
${sss!"abc"} <#--沒有定義這個變量,默認值是字符串abc!-->
??運算符返回布爾值,如:variable??,若是變量存在,返回true,不然返回false。通常狀況下與if指令共同使用。將它和if指令合併,以下面的例子:若是user變量不存在的話將會忽略整個問候代碼段:
<#if user??><h1>Welcome ${user}!</h1></#if>
關於多級訪問的變量,好比animals.python.price,書寫代碼:animals.python.price!0,僅當animals.python存在而僅僅最後一個子變量price可能不存在(這種狀況下咱們假設價格是0)。若是animals或者python不存在,那麼模板處理過程將會以「未定義的變量」錯誤而中止。爲了防止這種狀況的發生,能夠這樣來書寫代碼(animals.python.price)!0。這種狀況下當animals或python不存在時表達式的結果仍然是0。對於??也是一樣用來的處理這種邏輯的:animals.python.price??對比(animals.python.price)??來看。less

 

freemarker數據類型

freemarker的數據類型主要包括下面幾類:
字符串類型
定義字符串可使用雙引號和單引號,例如:
<#assign temp = "some text"  />
或者
<#assign temp = 'some text'  />
這兩種形式是相等的。字符串中可使用轉義字符"\"。若是字符串內有大量的特殊字符,則能夠在引號的前面加上一個字母r,則字符串內的全部字符都將直接輸出。例如:"It's \"quoted\"" 或者 r"C:\raw\string"
數字類型
輸入不帶引號的數字就能夠直接指定一個數字,必須使用點做爲小數的分隔符而不能是其餘的分組分隔符。可使用-或+來代表符號(+是多餘的)。科學記數法暫不支持使用(1E3就是錯誤的),並且也不能在小數點以前不寫0(.5也是錯誤的)。
哈希表類型
鍵和值成對出現並以冒號分隔,最外面使用花括號。看這個例子:
<#assign temp = {"name":"green mouse", "price":150} />
注意到名字和值都是表達式,可是用來檢索的名字就必須是字符串類型的。
序列類型
指定一個序列,使用逗號來分隔其中的每一個子變量,而後把整個列表放到方括號中。例如:
<#assign nums=[1,2,3,4,5,77,8,99]/>
使用list指令將序列輸出,以下所示:
<#list nums as num>
   ${num}
</#list>
還能夠採用數字範圍定義了一個連續的序列,例如:
<#assign nums=12..99/>
這種方式定義的序列的內容是12到99。總之,使用數字範圍也能夠表示一個數字集合,如1..5等同於集合[1,2, 3, 4, 5];一樣也能夠用5..1來表示[5, 4, 3, 2, 1]。
時間類型
FreeMarker支持date、time、datetime三種類型,這三種類型的值沒法直接指定,一般須要藉助字符串的date、time、datetime三個內建函數進行轉換才能夠:
 <#assign test1 = "2009-01-22"?date("yyyy-MM-dd") />;
 <#assign test2 ="16:34:43"?time("HH:mm:ss") />
 <#assign test2 = "2009-01-22 17:23:45"?datetime("yyyy-MM-dd HH:mm:ss") />
布爾類型
直接使用true或false,不使用引號。例如:<#assign temp = true />ide

 

freemarker的配置簡介

在freemarker啓動的過程當中,參與配置功能的類主要有四個:Configurable,Configuration,Template和Environment。下面給你們簡單介紹一下這裏類的特色,內容主要是出自freemarker的源碼,並且這些英文比較簡單,稍微耐心一點就能夠讀懂的。函數

Configurable簡介

This is a common superclass of {@link freemarker.template.Configuration},{@link freemarker.template.Template}, and {@link Environment} classes.
It provides settings that are common to each of them. FreeMarker uses a three-level setting hierarchy - the return value of every setting getter method on <code>Configurable</code> objects inherits its value from its parent <code>Configurable</code> object, unless explicitly overridden by a call to a corresponding setter method on the object itself. The parent of an 
<code>Environment</code> object is a <code>Template</code> object, the parent of a <code>Template</code> object is a <code>Configuration</code> object.學習

Configuration簡介

The main entry point into the FreeMarker API; encapsulates the configuration settings of FreeMarker, also serves as a central template-loading and caching service.
This class is meant to be used in a singleton pattern. That is, you create an instance of this at the beginning of the application life-cycle, set its {@link #setSetting(String, String) configuration settings} there (either with the setter methods like {@link #setTemplateLoader(TemplateLoader)} or by loading a {@code .properties} file), and then use that single instance everywhere in your application. Frequently re-creating {@link Configuration} is a typical and grave mistake from performance standpoint, as the {@link Configuration} holds the template cache, and often also the class introspection cache, which then will be lost. (Note that, naturally,having multiple long-lived instances,like one per component that internally uses FreeMarker is fine.)  
The basic usage pattern is like:
// Where the application is initialized; in general you do this ONLY ONCE in the application life-cycle!
Configuration cfg = new Configuration(VERSION_X_Y_Z));
// Where X, Y, Z enables the not-100%-backward-compatible fixes introduced in
// FreeMarker version X.Y.Z  and earlier (see {@link #Configuration(Version)}).
cfg.setSomeSetting(...);
cfg.setOtherSetting(...);網站

Template簡介

Stores an already parsed template, ready to be processed (rendered) for unlimited times, possibly from multiple threads.
Typically, you will use {@link Configuration#getTemplate(String)} to create/get {@link Template} objects, so you don't construct them directly. But you can also construct a template from a {@link Reader} or a {@link String} that contains the template source code. But then it's important to know that while the resulting {@link Template} is efficient for later processing, creating a new {@link Template} itself is relatively expensive. So try to re-use {@link Template} objects if possible.{@link Configuration#getTemplate(String)} does that (caching {@link Template}-s) for you, but the constructor of course doesn't, so it's up to you to solve then.
Objects of this class meant to be handled as immutable and thus thread-safe. However, it has some setter methods for changing FreeMarker settings. Those must not be used while the template is being processed, or if the template object is already accessible from multiple threads.

Environment簡介

Object that represents the runtime environment during template processing. For every invocation of a <tt>Template.process()</tt> method, a new instanceof this object is created, and then discarded when <tt>process()</tt> returns.This object stores the set of temporary variables created by the template,the value of settings set by the template, the reference to the data model root,etc. Everything that is needed to fulfill the template processing job.Data models that need to access the Environment object that represents the template processing on the current thread can use the {@link #getCurrentEnvironment()} method.If you need to modify or read this object before or after the process call, use {@link Template#createProcessingEnvironment(Object rootMap, Writer out, ObjectWrapper wrapper)}

相關文章
相關標籤/搜索