velocity.properties 的一些配置項
- velocimcro.library屬性:指定自己的模板庫,多個模板庫以逗號分隔。默認情況下,velocity查找唯一的一個庫:VM_global_library.vm
- velocimacro.permissions.allow.inline屬性:是否允許開發者在普通模板內定義Velocity宏。ho
- velocimacro.permissions.allow.inline.replace.global屬性: 是否允許設計者使用本地的inline的 宏替代全局的宏(全局的宏是指在velocimacro.library屬性中指定的文件內定義的宏)。默認情況下,此值爲false。這樣就阻止本地的宏覆蓋全局的。
- velocimacro.permissions.allow.inline.local.scale屬性: inline定義的宏是否僅僅在被定義的template內可見. 默認是false。 換句話說,如果這個屬性設置爲true,一個inline定義的宏只能在定義它的template內使用。
- velocimacro.context.localscope屬性: 默認值爲false。當設置爲true時,任何在宏內通過#set()對context的修改被認爲是針對此宏的本地設置,而不會永久的影響內容。
- velocimacro.library.autoreload屬性: 控制宏庫的自動加載。默認是false。當設置爲ture時,對於一個宏的調用將自動檢查原始庫是否發生了變化,如果變化將重新加載它。這個屬性使得你可以不用重新啓動servlet容器而達到重新加載的效果,就像你使用regular模板一樣。這個屬性可以使用的前提就是resource loader緩存是off狀態(file.resource.loader.cache = false)。注意這個屬性實際上是針對開發而非產品的。
Velocity宏的一些說明
Velocity宏必須定義在它們被使用之前,也就是說,你的#macro()聲明應該出現在使用宏之前。特別要注意的是,當你試圖#parse()一個包含#macro()的模板時候。因爲#parse()發生在運行期,但是解析器在parsetiem決定一個看似VM元素的元素是否是一個VM元素,這樣#parse()-ing一組VM聲明將不按照預期的樣子工作。爲了得到預期的結果,只需要你簡單的使用velocimacro.library使得Velocity在啓動時加載你的VMs。
再說Velocity的轉義符
我們已經知道使用反斜槓(\)進行轉義。下面總結一下:
1 |
##
#include( “a.txt” ) renders as < ontents of
a.txt>(註釋行) |
4 |
##
\#include( “a.txt” ) renders as \#include( “a.txt” ) |
7 |
##
\\#include ( “a.txt” ) renders as \< contents of
a.txt> |
在對在一個directive內包含多個script元素的VTL directives, 使用逃逸符時要特別小心(比如在一個if-else-end statement內)。下面是VTL的if-statement的典型應用:
如果$jazz是ture,輸出將是:
Vyacheslav Ganelin
如果$jazz是false,將沒有輸出。使用逃逸符將改變輸出。考慮一下下面的情況:
現在無論$jazz是true還是false,輸出結果都是:
#if ( $jazz )
Vyacheslav Ganelin
#end
事實上,由於你使用了逃逸符,$jazz根本就沒有被解析爲boolean型值。在逃逸符前使用逃逸符是合法的,例如:
以上程序的顯示結果爲:
\ Vyacheslav Ganelin
\
但是如果$jazz爲false,那麼將沒有輸出。(書上說會沒有輸出,但是我覺得應該還有有“\”字符被輸出。)
VTL:Formatting issues
儘管在此用戶手冊中VTL通常都開始一個新行,如下所示:
1 |
#set
( $imperial = [ “Munetaka”, “Koreyasu”, “Hisakira”, “Morikune” ] ) |
2 |
#foreach
( $shogun in $imperial ) |
但是像下面這種寫法也是可以的:
1 |
Send
me #set($foo = [“$10 and”,”a cake”])#foreach($a in $foo)$a #end please. |
上面的代碼可以被改寫爲:
2 |
#set
( $foo = [“$10 and “,”a cake”] ) |
3 |
#foreach
( $a in $foo ) |
或者
2 |
#set($foo
= [“$10 and “,”a cake”]) |
3 |
#foreach
($a in $foo )$a |
這兩種的輸出結構將一樣。
其他特性和雜項
- 在模板中可以使用Velocity內建的算術函數,如:加、減、乘、除
1 |
#set
( $foo = $bar + 3 ) |
2 |
#set
( $foo = $bar - 4 ) |
3 |
#set
( $foo = $bar * 6 ) |
4 |
#set
( $foo = $bar / 2 ) |
當執行除法時將返回一個Integer類型的結果。而餘數你可以使用%來得到:
1 |
#set
( $foo = $bar % 5 ) |
在Velocity內使用數學計算公式時,只能使用像-n,-2,-1,0,1,2,n這樣的整數,而不能使用其它類型數據。當一個非整型的對象被使用時它將被logged並且將以null作爲輸出結果。
Range Operator
Range operator可以被用於與#set和#foreach statement聯合使用。對於處理一個整型數組它是很有用的,Range operator具有以下構造形式:
m和n都必須是整型,而m是否大於n則無關緊要。例子:
First example:
1 |
#foreach
( $foo in [1..5] ) |
Second example:
1 |
#foreach
( $bar in [2..-2] ) |
Third example:
2 |
#foreach
( $i in $arr ) |
Fourth example:
上面四個例子的輸出結果爲:
First example:
1 2 3 4 5
Second example:
2 1 0 -1 -2
Third example:
0 1
Fourth example:
[1..3]
注意:range operator只在#set和#foreach中有效。
Advanced Issue:Escaping and!
當一個reference被“!”分隔時,並且在它之前有逃逸符時,reference將以特殊的方式處理。注意這種方式與標準的逃逸方式時不同的。對照如下:
特殊形式 標準格式
Render前 Render後 Render前 Render後
$\!foo $!foo \$foo \$foo
$\!{foo} $!{foo} \$!foo \$!foo
$\\!foo $\!foo \$!{foo} \$!{foo}
$\\\!foo $\\!foo \\$!{foo} \bar
Velocimacro雜記
- Can I user a directive or another VM as an argument to a VM? For example, #center ( #bold( “hello” ) )
不可以。 一個directive的參數使用另外一個directive是不合法的。
但是,還是有些事情你可以作的。最簡單的方式就是使用雙引號:
1 |
#set
( $stuff = "#bold( 'hello' )" ) |
上面的格式也可以縮寫爲一行:
1 |
#center
("#bold('hello')") |
請注意在下面的例子中參數被evaluated在Velocimacro內部,而不是在calling level。例子:
06 |
#set
( $bar = "outerlala" ) |
10 |
#set
( $bar = 'calltimelala' ) |
11 |
#outer(
"#inner($bar)" ) |
輸出結果爲:
outer : inner : outerlala
記住Veloctiy的特性:參數的傳遞是By Name的。例如:
2 |
< tr bgcolor
= $color >< td >Hi</ td ></ tr > |
3 |
< tr bgcolor
= $color >< td >There</ td ></ tr > |
6 |
#foo
( $bar.rowColor() ) |
以上代碼將導致rowColor()方法兩次調用,而不是一次。爲了避免這種現象的出現,我們可以按照下面的方式執行:
1 |
#set
( $color = $bar.rowColor() ) |
- can I register velocimacros via #parse()?
目前,Velocimacros必須在第一次被模板調用前被定義。這就意味着 你的#macro()聲明應該出現在使用Velocimacros之前。如果你試圖#parse()一個包含#macro() directive的模板,這一點是需要牢記的:因爲#parse()發生在運行期,但是解析器在parsetiem決定一個看似VM元素的元素是否是一個VM元素,這樣#parse()-ing一組VM聲明將不按照預期的樣子工作。爲了得到預期的結果,只需要你簡單的使用velocimacro.library使得Velocity在啓動時加載你的VMs。
- What is velocimacro autoreloading?
velocimacro.library.autoreload是專門爲開發而非產品使用的一個屬性。此屬性的默認值是false。
String concatenation
開發人員最常問的問題是我如何作字符拼接?在java中是使用“+”號來完成的。
在VTL裏要想實現同樣的功能你只需要將需要聯合的reference放到一起就行了。例如:
3 |
The
clock is $size$name. |
輸出結果將是:The clock is BigBen.。更有趣的情況是:
3 |
#set
( $clokc = “$size$name” ) |
上例也會得到同樣的結果。最後一個例子,當你希望混合固定字段到你的reference時,你需要使用標準格式:
3 |
#set
( $clock = "${size}Tall$name" ) |
輸出結果是:The clock is BigTallBen.。使用這種格式主要是爲了使得$size不被解釋爲$sizeTall。