Velocity用戶指南
什麼是Velocity?
Velocity是基於Java的模板引擎。它允許Web頁面開發者引用Java代碼中定義的方法。Web設計者可以和Java程序開發者並行開發遵循MVC模式的Web站點。這意味着,Web設計者可以將精力放在好的Web站點設計上,而Java程序開發者可以將精力放在編寫代碼上。Velocity將Java代碼從Web頁面中分離,使Web站點更具長期可維護性,並提供了一種替代JSP或PHP的方案。
VTL(Velocity Template Language)介紹
VTL提供一種簡單、容易和幹靜的方法將動態內容合併到Web頁面。VTL使用引用(references)將動態內容插入到Web頁面中。變量是一種引用,可以指向Java代碼中的定義內容,或者由Web頁面中的VTL語句來獲得值。下面是一個可以插入到HTML文檔的VTL語句的例子:
#set( $a = "Velocity" )
VTL語句以#開頭,幷包含指令(set)。變量以$開頭,用引號引起。引號可以是單引號,也可以是雙引號。前者引用具體的String值;後者可以包含Velocity引用,例如”hello, $name”, $name會用其當前的值替換。上面的例子是將值Velocity賦值給變量a。
當變量被賦值後,就可以在HTML文檔的任何地方引用,下面是Hello Velocity World!的例子:
<html>
<body>
#set( $foo = "Velocity" )
Hello $foo World!
</body>
<html>
註釋
VTL支持單行註釋(以##開始)和多行註釋(包括在#*和*#之間),下面是一個例子:
This text is visible. ## This text is not visible.
This text is visible.
This text is visible. #* This text, as part of a multi-line comment,
is not visible. This text is not visible; it is also part of the
multi-line comment. This text still not visible. *# This text is outside
the comment, so it is visible.
## This text is not visible.
引用
VTL有3種類型的引用:變量、屬性和方法。作爲一個設計者,必須和Java工程師在VTL引用的名稱(標識符)上一致,以便在模板中使用它們。引用是作爲String對象處理的。
(1)變量
變量的格式:$VTL標識符
VTL標識符以字母開始,由字母、數字、橫劃線(-)或下劃線(_)組成。變量或者從模板中的set指令獲得值(如前面的例子),或者Java代碼(同名變量)中獲得值。Velocity只處理已定義的變量引用,對於沒有定義的變量引用,Velocity原樣返回。例如下面的例子:
#set( $foo = "gibbous" )
$moon = $foo
輸出結果是:$moon = gibbous
(2)屬性
屬性的格式:$VTL標識符. VTL標識符
下面是屬性引用的例子:
$customer.Address
$purchase.Total
拿第一例子來說,有兩種意思:
l 返回Hashtable對象customer中鍵值爲Address的值
l $customer.getAddress()方法引用的縮寫(JavaBean屬性的getter方法)
至於是哪種情況,Velocity會做決定,返回合適的值。
(3)方法
方法的格式:$VTL標識符(參數列表)
下面是方法引用的例子:
$customer.getAddress()
$purchase.getTotal()
$page.setTitle( "My Home Page" )
$person.setAttributes( ["Strange", "Weird", "Excited"] )
前面兩個例子可以縮寫成屬性引用(如屬性引用的例子)。屬性引用和方法引用的主要區別是方法引用可以指定參數列表。
(4)正式引用符號:{}
正式引用符號在使用變量引用含糊的地方進行區分。看下面的例子:
#set( $vice = "klepto" )
Jack is a $vicemaniac.
輸出結果是:Jack is a $vicemaniac.($vicemaniac沒有定義,原樣輸出)
#set( $vice = "klepto" )
Jack is a ${vice}maniac.
輸出結果是:Jack is a kleptomaniac.(使用正式引用符號將$vice和其它文本區分開)
(5)Quit引用符號:!
看下面的例子:
<input type="text" name="email" value="$email"/>
初始時,$email沒有值,所以文本框中會顯示值$email,而更希望是空白。下面是使用Quit引用符號的例子:
<input type="text" name="email" value="$!email"/>
當$email沒有值時,Velocity會用空串替代$email。
(6)特殊字符轉義
對於$、#等特殊字符要正常顯示,可以使用/進行轉義,//轉義爲/。下面是一個例子:
#set( $email = "foo" )
輸出結果是:
foo
/foo
指令(Directives)
引用允許模板設計者爲Web站點生成動態內容,而指令使巧妙處理Java代碼的腳本元素容易使用。
(1)#set
格式:#set( LHS = RHS )
l LHS可以是變量引用或屬性引用
l RHS可以是引用、字符串、數字、ArrayList或Map
下面的例子展示了上面的每種RHS類型:
#set( $monkey = $bill ) ## variable reference
#set( $monkey.Friend = "monica" ) ## string literal
#set( $monkey.Blame = $whitehouse.Leak ) ## property reference
#set( $monkey.Plan = $spindoctor.weave($web) ) ## method reference
#set( $monkey.Number = 123 ) ##number literal
#set( $monkey.Say = ["Not", $my, "fault"] ) ## ArrayList
#set( $monkey.Map = {"banana" : "good", "roast beef" : "bad"}) ## Map
對於ArrayList和Map,可以使用對應的Java方法訪問其中的元素值:
$monkey.Say.get(0)
$monkey.Map.get("bannana")
$monkey.Map.banana ## same as above
l RHS可以是簡單的算術表達式
#set( $value = $foo + 1 ) ## Addition
#set( $value = $bar - 1 ) ## Subtraction
#set( $value = $foo * $bar ) ## Multiplication
#set( $value = $foo / $bar ) ## Division
#set( $value = $foo % $bar ) ## Remainder
算術表達式只支持整型。/的結果爲整數;如果非整型數值,返回null
l 如果RHS的結果爲null,是不會賦值給LHS的
看下面的例子:
#set( $criteria = ["name", "address"] )
#foreach( $criterion in $criteria )
#set( $result = $query.criteria($criterion) )
#if( $result )
Query was successful
#end
#end
上面使用$result檢查是否執行成功是有問題的。如果第一次執行成功,$result不爲null,則後面的執行不管是否成功,檢查條件總是成立。改進的方法是在每次執行前初始化爲false:
#set( $criteria = ["name", "address"] )
#foreach( $criterion in $criteria )
#set( $result = false )
#set( $result = $query.criteria($criterion) )
#if( $result )
Query was successful
#end
#end
l String文字可以使用雙引號或單引號括起。兩者的主要區別是雙引號中的引用會替換成相應的值,而單引號中的引用原樣輸出
#set( $directoryRoot = "www" )
#set( $templateName = "index.vm" )
#set( $template = "$directoryRoot/$templateName" )
$template
輸出結果是:www/index.vm
如果使用單引號:
#set( $template = '$directoryRoot/$templateName’ )
輸出結果是:$directoryRoot/$templateName
l 使用雙引號可以實現字符串的串聯,如下面的例子:
#set( $size = "Big" )
#set( $name = "Ben" )
#set($clock = "${size}Tall$name" )
The clock is $clock.
(2)#if / #elseif / #else
#if指令在條件成立時,顯示#if和#end之間的內容,否則顯示#else和#end之間的內容。下面是一個例子:
#if( $foo )
<strong>Velocity!</strong>
#end
條件成立有兩種情況:
l 如果$foo是boolean,則$foo要爲true;
l 否則,$foo不爲null
#if指令中可以使用的關係和邏輯符號包括:
l <、<=、==、>=、>
l &&(and)、||(or)、!(not)
(3)循環:foreach
下面是一個例子:
<ul>
#foreach( $product in $allProducts )
<li>$product</li>
#end
</ul>
$allProducts的內容可以是Vector、Hashtable或ArrayList,每次取出一個值賦值給$product;返回的值是一個Java對象,可以用來引用具體的方法。下面的例子假設$allProducts是Hashtable對象:
<ul>
#foreach( $key in $allProducts.keySet() )
<li>Key: $key -> Value: $allProducts.get($key)</li>
#end
</ul>
Velocity提供了訪問循環計數變量的簡單方法:
<table>
#foreach( $customer in $customerList )
<tr><td>$velocityCount</td><td>$customer.Name</td></tr>
#end
</table>
$velocityCount是Velocity表示循環計數的內部變量,缺省開始值爲1。該設置在velocity.properties文件中定義:
# Default name of the loop counter
# variable reference.
directive.foreach.counter.name = velocityCount
# Default starting value of the loop
# counter variable reference.
directive.foreach.counter.initial.value = 1
可以在#foreach指令中使用範圍操作符[n..m],其中n和m必須是整型:
First example:
#foreach( $foo in [1..5] )
$foo
#end
Second example:
#foreach( $bar in [2..-2] )
$bar
#end
Third example:
#set( $arr = [0..1] )
#foreach( $i in $arr )
$i
#end
輸出結果是:
First example:
1 2 3 4 5
Second example:
2 1 0 -1 -2
Third example:
0 1
(4)#include
#include指令導入本地文件到#include指令定義的地方。導入的文件內容不會被模板引擎解析。出於安全考慮,導入的文件應該放在TEMPLATE_ROOT目錄下。一次可以導入多個文件,文件名之間用逗號分隔;並且通常使用變量引用來替代文件名。下面是一個例子:
#include( "greetings.txt", $seasonalstock )
(5)#parse
#parse指令允許導入一個包含VTL的本地文件,並由模板引擎進行解析。#parse指令導入的文件必須放在TEMPLATE_ROOT目錄下,並且一次只能導入一個文件。允許在Velocity模板中嵌套執行#parse指令。最大深度由velocity.properties文件中的parse_directive.maxdepth定義。下面是一個例子:
Count down.
#set( $count = 8 )
#parse( "parsefoo.vm" )
All done with dofoo.vm!
包含的parsefoo.vm文件如下:
$count
#set( $count = $count - 1 )
#if( $count > 0 )
#parse( "parsefoo.vm" )
#else
All done with parsefoo.vm!
#end
輸出結果是:
Count down.
8
7
6
5
4
3
2
1
0
All done with parsefoo.vm!
All done with dofoo.vm!
(6)#stop
#stop指令停止模板引擎的執行並返回。這在Debug時很有用。
#macro( tablerows $color $somelist )
#foreach( $something in $somelist )
<tr><td bgcolor=$color>$something</td></tr>
#end
#end
#set( $greatlakes = ["Superior","Michigan","Huron","Erie","Ontario"] )
#set( $color = "blue" )
<table>
#tablerows( $color $greatlakes )
</table>
<table>
<tr><td bgcolor="blue">Superior</td></tr>
<tr><td bgcolor="blue">Michigan</td></tr>
<tr><td bgcolor="blue">Huron</td></tr>
<tr><td bgcolor="blue">Erie</td></tr>
<tr><td bgcolor="blue">Ontario</td></tr>
</table>
velocimacro.library = VM_global_library.vm
velocimacro.permissions.allow.inline = true
velocimacro.permissions.allow.inline.to.replace.global = false
velocimacro.permissions.allow.inline.local.scope = false
velocimacro.context.localscope = false
velocimacro.library.autoreload = false
#center( #bold("hello") ) ##invalid
#center( "#bold( 'hello' )" ) ##right
#macro( inner $foo )
inner : $foo
#end
#macro( outer $foo )
#set($bar = "outerlala")
outer : $foo
#end
#set($bar = 'calltimelala')
#outer( "#inner($bar)" )