Velocity User Guide 用戶手冊

英文來源: http://jakarta.apache.org/velocity/docs/user-guide.htmlhtml

關於這個用戶手冊java

Velocity用戶手冊是幫助頁面設計者和內容提供者認識Velocity和其簡單而功能強大的腳本語言――Velocity模板語言(VTL)。在手冊上的許多例子,都是用Velocity插入動態的內容到網頁上,可是全部的VLT例子都能應用到其餘的頁面和模板中。web

感謝使用 Velocity!數據庫

Velocity是什麼?apache

Velocity是一個基於java的模板引擎(template engine)。它容許任何人僅僅簡單的使用模板語言(template language)來引用由java代碼定義的對象。api

Velocity應用於web開發時,界面設計人員能夠和java程序開發人員同步開發一個遵循MVC架構的web站點,也就是說,頁面設計人員能夠只關注頁面的顯示效果,而由java程序開發人員關注業務邏輯編碼。Velocityjava代碼從web頁面中分離出來,這樣爲web站點的長期維護提供了便利,同時也爲咱們在JSPPHP以外又提供了一種可選的方案。數組

Velocity的能力遠不止web站點開發這個領域,例如,它能夠從模板(template)產生SQLPostScriptXML,它也能夠被看成一個獨立工具來產生源代碼和報告,或者做爲其餘系統的集成組件使用。Velocity也能夠爲Turbine web開發架構提供模板服務(template service)。Velocity+Turbine提供一個模板服務的方式容許一個web應用以一個真正的MVC模型進行開發。緩存

 

Velocity能爲咱們做什麼?安全

Mud 商店例子架構

假設你是一家專門出售Mud的在線商店的頁面設計人員,讓咱們暫且稱它爲在線MUD商店。大家的業務很旺,客戶下了各類類型和數量的mud訂單。他們都是經過輸入用戶名和密碼後才登錄到你的網站,登錄後就容許他們查看訂單併購買更多的mud。如今,一種很是流行的mud正在打折銷售。另外有一些客戶規律性的購買另一種也在打折可是不是很流行的Bright Red Mud,因爲購買的人並很少因此它被安置在頁面的邊緣。全部用戶的信息都是被跟蹤並存放於數據庫中的,因此某天有一個問題可能會冒出來:爲何不使用velocity來使用戶更好的瀏覽他們感興趣的商品呢?

Velocity使得web頁面的客戶化工做很是容易。做爲一個web site的設計人員,你但願每一個用戶登錄時都擁有本身的頁面。

你會見了一些公司內的軟件工程師,你發現他們每一個人都贊成客戶應該擁有具備個性化的信息。那讓咱們把軟件工程師應該做的事情發在一邊,看一看你應該做些什麼吧。

你可能在頁面內嵌套以下的VTL聲明:

<HTML>

<BODY>

Hello $customer.Name!

<table>

#foreach( $mud in $mudsOnSpecial )

   #if ( $customer.hasPurchased($mud) )

      <tr>

        <td>

          $flogger.getPromo( $mud )

        </td>

      </tr>

   #end

#end

</table>

foreach 的詳細用法不久就會進行深刻描述。重要的是,這短小的腳本能在你的網站上出現。當一個對Bright Red Mud 很感興趣的顧客登錄的時候,同時Bright Red Mud在熱賣中,這時顧客就能顯著地看到。假如一個玩Terracotta Mud好久的顧客登錄,Terracotta Mud 的售賣信息就會出如今前面中間。Velocity的適用性是很巨大的,限制的只是你的創造性。

     VTL Reference 含有許多其餘Velocity元素,這些元素可以共同幫助你,使你的網站更加好。當你愈來愈熟悉那些原理,你開始釋放Velocity的能力。

Velocity模板語言(VTL):說明

VTL意味着提供最簡單、最容易而且最整潔的方式合併頁面動態內容。VTL使用references來在web site內嵌套動態內容,一個變量就是一種類型的reference。變量是某種類型的refreence,它能夠指向java代碼中的定義,或者從當前頁面內定義的VTL statement獲得值。下面是一個VTL statement的例子,它能夠被嵌套到HTML代碼中:

#set( $a = "Velocity" )

和全部的VTL statement同樣,這個statement以#字符開始而且包含一個directiveset。當一個在線用戶請求你的頁面時,Velocity 模板引擎將查詢整個頁面以便發現全部#字符,而後肯定哪些是VTL statement,哪些不須要VTL做任何事情。

#字符後緊跟一個directiveset時,這個set directive使用一個表達式(使用括號封閉)――一個方程式分配一個值給變量。變量被列在左邊,而它的值被列在右邊,最後他們之間使用=號分割。

在上面的例子中,變量是$a,而它的值是Velocity。和其餘的references同樣以$字符開始,而值老是以雙引號封閉。Velocity中僅有String能夠被賦值給變量。

使用$字符開始的references用於獲得什麼;使用#字符開始的directives用於做些什麼。在上面的例子中,#set是分配一個值給變量。變量$a 在模板中輸出 "Velocity"。

 

Hello Velocity World!

一旦某個變量被分配了一個值,那麼你就能夠在HTML文件的任何地方引用它。在下面的例子中,一個值被分配給$foo變量,並在其後被引用。

<html>

<body>

#set( $foo = "Velocity" )

Hello $foo World!

</body>

<html>

上面的實現結果是在頁面上打印「Hello Velocity World

爲了使包含VTL directivesstatement更具備可讀性,咱們鼓勵你在新行開始每一個VTL statement,儘管你不是必須這麼做。Set的用法將在後面詳細描述。

 

註釋

         註釋是那些描述文本不出如今模板引擎輸出裏面。註釋一個主要用處是提醒本身和解釋出如今VTL中的聲明,或是其餘用途。下面是一個在VLT中的註釋例子。

## This is a single line comment.

單行註釋以##開始,結束在這行的結尾。若是你要寫幾行註釋,這沒有必要寫幾個單行註釋。

多行註釋,以#*開始*#結束,能夠解決這個問題。

This is text that is outside the multi-line comment.

Online visitors can see it.

 

#*

 Thus begins a multi-line comment. Online visitors won't

 see this text because the Velocity Templating Engine will

 ignore it.

*#

 

Here is text outside the multi-line comment; it is visible.

這裏有幾個例子關於單行和多行註釋如何工做。

This text is visible. ## This text is not.

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.

這裏有第三種類型的註釋,VLT註釋塊,可能用於存放文檔的做者名稱和版本信息。

#**

This is a VTL comment block and

may be used to store such information

as the document author and versioning

information:

@author

@version 5

*#

 

References

 

VTL中有三種類型的references:變量(variables)、屬性(properties)、方法(methods)。做爲一個使用VTL的頁面設計者,你和你的工程師必須就references的名稱達成共識,以便你能夠在你的template中使用它們。

全部的  reference被做爲一個String對象處理。若是有一個對象$foo是一個Integer對象,那麼Velocity將調用它的toString()方法將這個對象轉型爲String類型。

 

變量

非正式變量是由「$」開頭,接着是VTL標識符。VLT標識符必須以字母(a..z,A..Z)開頭。剩下的部分限於如下幾種:

l          字母(a..z,A..Z)

l          數字(0..9)

l          連字符(「-」)

l          下劃線(「_」)

這裏是幾個在VTL中有效的變量reference

$foo

$mudSlinger

$mud-slinger

$mud_slinger

$mudSlinger1

VLT定義一個變量,例如$foo,變量能或者經過模板中的set 方法,或者經過Java 代碼得到值。

例如,Java 變量 $foo 的值是 bar ,在這個模板被請求時,在網頁上 bar 會替代全部 $foo 。選擇地,假如包括了下面的聲明:

#set( $foo = "bar" )

按照這樣的設置,輸出就會跟以前的同樣。

 

屬性

第二種有趣的VTL reference就是屬性,並且屬性有一種不同凡響的格式。非正式變量是由「$」開頭,接着是VTL標識符,再接着就是字符(「.」)和其餘的VLT標識符。這裏是一些在VLT中有效屬性的定義:

$customer.Address

$purchase.Total

在第一個例子中$customer.Address有兩種含義。它能夠表示:查找hashtable對象customer中以Address爲關鍵字的值;也能夠表示調用customer對象的getAddress()方法。當你的頁面被請求時,Velocity將肯定以上兩種方式選用那種,而後返回適當的值。

 

方法

一個方法就是被定義在java中的一段代碼,而且它有完成某些有用工做的能力,例如一個執行計算和判斷條件是否成立、知足等。方法是一個由$開始並跟隨VTL標識符組成的References,通常還包括一個VTL方法體。一個VTL方法體包括一個VLT標識接着一個左括號(「(」),接着是參數列表,再接着是右括號(「)」)。這裏是一些在VTL中有效的方法定義:

$customer.getAddress()

$purchase.getTotal()

$page.setTitle( "My Home Page" )

$person.setAttributes( ["Strange", "Weird", "Excited"] )

前兩個例子$customer.getAddress()$purchase.getTotal()看起來挺想上面的屬性$customer.Address  $purchase.Total。若是你以爲他們之間有某種聯繫的話,那你是正確的。

VTL屬性能夠做爲VTL方法的縮寫。$customer.Address屬性和使用$customer.getAddress()方法具備相同的效果。若是可能的話使用屬性的方式是比較合理的。屬性和方法的不一樣點在於你可以給一個方法指定一個參數列表。

非正式定義可以用下面的方法:

$sun.getPlanets()

$annelid.getDirt()

$album.getPhoto()

咱們期待那些方法返回屬於太陽系的行星的名稱,餵養咱們的蚯蚓,或者從相冊裏面取出一張照片。只有長符號爲下面的方法服務。

$sun.getPlanet( ["Earth", "Mars", "Neptune"] )

## Can't pass a parameter list with $sun.Planets

 

$sisyphus.pushRock()

## Velocity assumes I mean $sisyphus.getRock()

 

$book.setTitle( "Homage to Catalonia" )

## Can't pass a parameter list

 

正式reference標記

非正式references用於上述的例子中。可是一樣有正式的references,以下面所示:

${mudSlinger}

${customer.Address}

${purchase.getTotal()}

在幾乎全部場合你均可以使用非正式references,可是在某些場合,只能使用正式reference 才能正確處理。

設想你建立一個句子:$vice 做爲句子的名詞 。目標是爲了使某些人選擇不一樣的詞,產生下面兩種結果之一:"Jack is a pyromaniac." 或者 "Jack is a kleptomaniac."。使用非正式定義不太適合用於這種狀況。看一下下面的例子:

Jack is a $vicemaniac.

原本變量是$vice如今卻變成了$vicemaniac,這樣Veloctiy就不知道您到底要什麼了。因此,應該使用正是格式書寫

Jack is a ${vice}maniac.

如今Velocity就知道reference $vice,而不是$vicemaniac。正式定義常常用於模板中refernces與文本鏈接在一塊兒的狀況。

 

Quiet reference notation

Velocity遇到沒有定義的reference,一般它會直接輸出reference。例如:假以下面的reference出如今一個VTL模板中:

<input type="text" name="email" value="$email"/>

 form 最初加載的時候,變量$email 沒有值,但你想出現一個空白的文本框設定值爲「$email」。

使用quiet reference notation可使Velocity正常顯示,你須要用$!email ,代替$email。因此上面的例子,會改爲下面:

<input type="text" name="email" value="$!email"/>

這樣文本框的初始值就不會是email而是空值了。

正式和quiet格式的reference notation也可一同使用,像下面這樣:

<input type="text" name="email" value="$!{email}"/>

 

Getting literal

Velocity使用特殊字符$#來幫助它工做,因此若是要在template裏使用這些特殊字符要格外當心。本節將討論$字符。

貨幣字符

這是沒有問題的:"I bought a 4 lb. sack of potatoes at the farmer's market for only $2.50!"VTL中使用$2.5這樣的貨幣標識是沒有問題得的,VTL不會將它錯認爲是一個reference,由於VTL中的reference老是以一個大寫或者小寫的字母開始。

 

Escaping valid VTL reference

某些狀況使用Velocity可能會以爲很煩惱。逃避特殊符是處理出如今你的模板中VTL特殊符有效方法,就是使用反斜槓(「\」)

#set( $email = "foo" )

$email

假如Velocity在你的模板中遇到 $email ,它會搜索上下文,獲得相應的值。這裏的輸出是 foo ,由於 $email 被定義了。假如  $email 沒有被定義,輸出會是 $email 

設想 $email 被定義了(例如,它的值是 foo ),並且你想輸出 $email 。這裏有幾種方法能達到目的,可是最簡單的是使用逃避符。

## The following line defines $email in this template:

#set( $email = "foo" )

$email

\$email

\\$email

\\\$email

將顯示爲:

foo

$email

\foo

\$email

注意到 \ 屏蔽了左邊的 $」。屏蔽左邊規則,使得 \\\$email 顯示爲 \\$email 。那些例子與 $email沒有定義相比較。

$email

\$email

\\$email

\\\$email

將顯示爲:

$email

\$email

\\$email

\\\$email

注意Velocity處理 定義了的references 與沒有定義的不同。這裏 set $foo 的值爲 gibbous

#set( $foo = "gibbous" )

$moon = $foo

輸出會是:$moon = gibbous ,$moon 按照字面上輸出由於它沒有定義,gibbous 替代 $foo 輸出。

避開VTL directives 還有其餘方法,在 Directives 那章節會更詳細描述。

 

Case substitution

如今你已經對reference比較熟悉了,你能夠將他們高效的應用於你的template了。Velocity利用了不少java規範以方便了設計人員的使用。例如:

$foo

 

$foo.getBar()

## is the same as

$foo.Bar

 

$data.getUser("jon")

## is the same as

$data.User("jon")

 

$data.getRequest().getServerName()

## is the same as

$data.Request.ServerName

## is the same as

${data.Request.ServerName}

那些例子說明了一樣的references 用法。Velocity 利用Java instrospection  bean features解決 reference 的名稱對於對象和對象方法的問題。它能夠出入你的模板中和求出 references 的值。

Velocity 是模仿Sun微系統中的Bean規範定義的,於是它是很靈活的。然而,它的開發者已經很努力地捕捉和糾正可能出現的錯誤。當方法 getFoo() 在模板中  $bar.foo調用時,Velocity首先嚐試 $getfoo。若是失敗,它會繼續嘗試 $getFoo。一樣地,當模板查詢 $bar.FooVelocity會先嚐試 $getFoo(),而後再嘗試 $getfoo()

可是,注意VTL中不會將reference解釋爲對象的實例變量。例如:$foo.Name將被解釋爲Foo對象的getName()方法,而不是Foo對象的Name實例變量。

 

Directives

Reference容許設計者使用動態的內容,而directive使得你能夠應用java代碼來控制你的顯示邏輯,從而達到你所指望的顯示效果。

#set

#set標誌是用於對一個reference賦值。值會賦給一個變量或者一個屬性,並且賦值會在括號裏出現:

#set( $primate = "monkey" )

#set( $customer.Behavior = $primate )

左邊(LHS) 必定是一個變量或者一個屬性。右邊(RHS)能夠是下面中的一個類型:

l          變量

l          字符串

l          屬性

l          方法

l          數字

l          數組

這些例子顯示上述的每一種類型:

#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

注意:最後一個例子的取值方法爲:$monkey.Say.get(0)

RHS也能夠是一個簡單的算術表達式:

#set( $value = $foo + 1 )

#set( $value = $bar - 1 )

#set( $value = $foo * $bar )

#set( $value = $foo / $bar )

若是你的RHS是一個nullVTL的處理將比較特殊:它將指向一個已經存在的reference,這對初學者來說多是比較費解的。例如:

#set( $result = $query.criteria("name") )

The result of the first query is $result

 

#set( $result = $query.criteria("address") )

The result of the second query is $result

若是$query.criteria(「name」)返回一個「bill」,而$query.criteria(「address」)返回的是null,則顯示的結果以下:

The result of the first query is bill

 

The result of the second query is bill

這容易使新手糊塗:建立一個#foreach循環,企圖想經過一個屬性或者一個方法 #set一個reference,而後立刻就用 #if 測試。例如:

#set( $criteria = ["name", "address"] )

 

#foreach( $criterion in $criteria )

 

    #set( $result = $query.criteria($criterion) )

 

    #if( $result )

        Query was successful

    #end

 

#end

在上面的例子中,程序將不能智能的根據$result的值決定查詢是否成功。在$result#set後(added to the context),它不能被設置回nullremoved from the context)。打印的結果將顯示兩次查詢結果都成功了,可是實際上有一個查詢是失敗的。

爲了解決以上問題咱們能夠經過預先定義的方式:

#set( $criteria = ["name", "address"] )

 

#foreach( $criterion in $criteria )

 

    #set( $result = false )

    #set( $result = $query.criteria($criterion) )

 

    #if( $result )

        Query was successful

    #end

 

#end

不像其餘Velocity指示符號,#set 沒有一個#end 結束。

 

String Literals

當你使用#set directiveString literal封閉在一對雙引號內。象下面:

#set( $directoryRoot = "www" )

#set( $templateName = "index.vm" )

#set( $template = "$directoryRoot/$templateName" )

$template

上面這段代碼的輸出結果爲:

www/index.vm

可是,當string literal被封裝在單引號內時,它將不被解析:

#set( $foo = "bar" )

$foo

#set( $blargh = '$foo' )

$blargh

輸出爲:

bar $foo

上面這個特性能夠經過修改velocity.properties文件的stringliterals.interpolate = false的值來改變上面的特性是否有效。

 

條件語句

If / ElseIf / Else

當一個web頁面被生成時使用Velocity#if directrive,若是條件成立的話能夠在頁面內嵌入文字。例如:

#if( $foo )

   <strong>Velocity!</strong>

#end

上例中的條件語句將在如下兩種條件下成立:(i)$foo是一個boolean型的變量,且它的值爲true(ii)$foo變量的值不爲null。這裏須要注意一點:Velocity context僅僅可以包含對象,因此當咱們說「boolean」時實際上表明的時一個Boolean對象。即使某個方法返回的是一個boolean值,Velocity也會利用內省機制將它轉換爲一個Boolean的相同值。

若是條件成立,那麼#if#end之間的內容將被顯示。在這個例子中,若是 $foo的值爲true,輸出爲「Velocity!」。相反地,若是 $foo 是一個 null值,或者是一個 false 值,表達式值爲 false,沒有輸出。

#elseif#else元素能夠同#if一同使用。注意:Velocity 模板引擎遇到一個爲true值的表達式就會中止。在下面的例子,假設 $foo=15,$bar=6

#if( $foo < 10 )

    <strong>Go North</strong>

#elseif( $foo == 10 )

    <strong>Go East</strong>

#elseif( $bar == 6 )

    <strong>Go South</strong>

#else

    <strong>Go West</strong>

#end

在這個例子中,$foo10大,因此在開始的兩個比較中都失敗。接着 $bar6比較是真的因此輸出爲 GO South

注意這裏的Velocity的數字是做爲Integer來比較的――其餘類型的對象將使得條件爲false,可是與java不一樣它使用==來比較兩個值,並且velocity要求等號兩邊的值類型相同。

 

關係、邏輯運算符

Velocity中使用等號操做符判斷兩個變量的關係。這裏有個簡單例子關於等於號的使用:

#set ($foo = "deoxyribonucleic acid")

#set ($bar = "ribonucleic acid")

 

#if ($foo == $bar)

  In this case it's clear they aren't equivalent. So...

#else

  They are not equivalent and this will be the output.

#end

VelocityANDORNOT邏輯運算符。想獲得更多信息,請看VTL Reference Guide。下面的例子是說明ANDORNOT邏輯運算符的用法:

## logical AND

 

#if( $foo && $bar )

   <strong> This AND that</strong>

#end

只有當$foo  $bar 都爲true#if 纔會獲得true值。若是$foofalse ,表達式的值爲 false$bar 就不會求值。若是 $foo的值爲 true Velocity模板引擎會檢查 $bar的值,若是$bar=true,整個表達式的值爲true,輸出爲「This AND that」。若是$bar=false,整個表達式的值爲false,沒有輸出。

邏輯OR 的工做方式同樣,除了只要有一個值爲true ,整個表達式的值就爲true。考慮一下下面的例子。

## logical OR

 

#if( $foo || $bar )

    <strong>This OR That</strong>

#end

若是$footrueVelocity模板引擎就沒有必要查找 $bar,不管 $bar true 仍是 false ,表達式的值爲 true ,輸出爲「This OR That」。若是$fooflase$bar的值就必定要檢查,在這個例子中,若是 $bar 一樣是false,表達式的值爲 false ,沒有輸出。從另一個角度看,若是$bar 的值爲true ,整個表達式的值爲 true ,輸出爲 This OR That」。

關於邏輯NOT ,只有一個疑問:

##logical NOT

 

#if( !$foo )

  <strong>NOT that</strong>

#end

若是 $foo=true, !$foo 的值爲 false,沒有輸出。若是$foo=false!$foo的值爲true,輸出爲「NOT that」。注意不要跟 quiet reference $!foo 混爲一談,那是徹底不同的。

 

循環

Foreach循環

#foreach 用於循環。例子:

<ul>

#foreach( $product in $allProducts )

    <li>$product</li>

#end

</ul>

每次循環$allProducts中的一個值都會賦給$product變量。

$allProducts能夠是一個VectorHashtable或者Array。分配給$product的值是一個java對象,而且能夠經過變量被引用。例如:若是$product是一個javaProduct類,而且這個產品的名字能夠經過調用他的getName()方法獲得。

如今咱們假設$allProducts是一個Hashtable,若是你但願獲得它的key應該像下面這樣:

<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默認的名字,你也能夠經過修改velocity.properties文件來改變它。默認狀況下,計數從「1」開始,可是你能夠在velocity.properties設置它是從「1」仍是從「0」開始。下面就是文件中的配置:

# 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

 

include

#include script element容許模板設計者引入本地文件。被引入文件的內容將不會經過模板引擎被render。爲了安全的緣由,被引入的本地文件只能在TEMPLATE_ROOT目錄下。

#include( "one.txt" )

#include 引用的文件用引號括起來。

若是您須要引入多個文件,能夠用逗號分隔就行:

#include( "one.gif","two.txt","three.htm" )

在括號內能夠是文件名,可是更多的時候是使用變量的。這用於根據頁面提交的需求而輸出。這裏有一個例子同時有文件名和變量。

#include( "greetings.txt", $seasonalstock )

 

parse

#parse script element容許模板設計者一個包含VTL的本地文件。Velocity將解析其中的VTLrender模板。

#parse( "me.vm" )

就像#include#parse接受一個變量而不是一個模板。任何由#parse指向的模板都必須包含在TEMPLATE_ROOT目錄下。與#include不一樣的是,#parse只能指定單個對象。

你能夠經過修改velocity.properties文件的parse_direcive.maxdepth的值來控制一個template能夠包含的最多#parse的個數――默認值是10#parse是能夠遞歸調用的,例如:若是dofoo.vm包含以下行:

Count down.

#set( $count = 8 )

#parse( "parsefoo.vm" )

All done with dofoo.vm!

那麼在parsefoo.vm模板中,你能夠包含以下VTL

$count

#set( $count = $count - 1 )

#if( $count > 0 )

    #parse( "parsefoo.vm" )

#else

    All done with parsefoo.vm!

#end

在顯示「Count down」後,Velocity經過parsefoo.vm,從8往下數。當計數到了0,它就會顯示「All done with parsefoo.vm!」。在這時,Velocity 會返回到dofoo.vm ,輸出信息:「All done with dofoo.vm!」。

 

 

中止

#stop script element容許模板設計者中止執行模板引擎並返回。把它應用於debug是頗有幫助的。

#stop

 

 

Velocimacros

#macro script element容許模板設計者定義一段可重用的VTL templateVelocimacros普遍用於簡單和複雜的行列。Velocimacros的出現是爲了減小編碼和極小化排版錯誤,對Velocimacros的概念提供一個介紹。

#macro( d )

<tr><td></td></tr>

#end

在上面的例子中Velocimacro被定義爲d,而後你就能夠在任何VTL directive中以以下方式調用它:

#d()

當你的template被調用時,Velocity將用<tr><td></td></tr>替換爲#d()

每一個Velocimacro能夠擁有任意數量的參數――甚至0個參數,雖然定義時能夠隨意設置參數數量,可是調用這個Velocimacro時必須指定正確的參數。下面是一個擁有兩個參數的Velocimacro,一個參數是color另外一個參數是array

#macro( tablerows $color $somelist )

#foreach( $something in $somelist )

    <tr><td bgcolor=$color>$something</td></tr>

#end

#end

Velocimacro在這個例子的定義,tablerows,有兩個元素。第一個是替換 $color ,第二個是替換$somelist

任何東西均可以經過Velocimacro加入到VTL模板中。tablerows Velocimacro 是一個foreach 標識。 這裏有兩個#end標識在#tablerows Velocimacro 定義裏面。第一個是屬於 #foreach,第二個是屬於Velocimacro定義的。

#set( $greatlakes = ["Superior","Michigan","Huron","Erie","Ontario"] )

#set( $color = "blue" )

<table>

    #tablerows( $color $greatlakes )

</table>

注意到$greatlakes 替代 $somelist。當#tablerows Velocimacro被調用時,就會產生下面的輸出:

<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>

Velocimacros能夠在Velocity模板內實現行內定義(inline),也就意味着同一個web site內的其餘Velocity模板不能夠得到Velocimacros的定義。定義一個能夠被全部模板共享的Velocimacro顯然是有不少好處的:它減小了在一大堆模板中重複定義的數量、節省了工做時間、減小了出錯的概率、保證了單點修改。

上面定義的#tablerows( $color $list )Velocimacro被定義在一個Velocimacros模板庫(velocity.properties中定義)裏,因此這個macro能夠在任何規範的模板中被調用。它能夠被屢次應用而且能夠應用於不一樣的目的。例以下面的調用:

#set( $parts = ["volva","stipe","annulus","gills","pileus"] )

#set( $cellbgcol = "#CC00FF" )

<table>

#tablerows( $cellbgcol $parts )

</table>

當爲mushroom.vm實現一個請求時,Velocity會在模板庫中找到#tablerows Velocimacro(定義在velocity.properties文件),產生如下輸出:

<table>

    <tr><td bgcolor="#CC00FF">volva</td></tr>

    <tr><td bgcolor="#CC00FF">stipe</td></tr>

    <tr><td bgcolor="#CC00FF">annulus</td></tr>

    <tr><td bgcolor="#CC00FF">gills</td></tr>

    <tr><td bgcolor="#CC00FF">pileus</td></tr>

</table>

 

Velocimacro arguments

Velocimacro可使用如下任何元素做爲參數:

l          Reference:任何以$開頭的reference

l          String literal

l          Number literal

l          IntegerRange[1….3]或者[$foo….$bar]

l          對象數組:[「a」,」b」,」c」]

l          boolean值:truefalse

當將一個reference做爲參數傳遞給Velocimacro時,請注意reference做爲參數時是以名字的形式傳遞的。這就意味着參數的值在每次Velocimacro內執行時纔會被產生。這個特性使得你能夠將一個方法調用做爲參數傳遞給Velocimacro,而每次Velocimacro執行時都是經過這個方法調用產生不一樣的值來執行的。例如:

     #macro( callme $a )

         $a $a $a

     #end

     #callme( $foo.bar() )

執行的結果是:reference $foobar()方法被執行了三次。

         在第一次掃描中,出現驚人的做用。可是當你考慮到Velocimacro的最原始動機:消除剪切、粘貼、複製,簡單地使用VTL使它更靈活。它容許你對傳遞對象到Velocimacro,例如一個產生重複序列顏色,着色表格的行的對象。

若是你不須要這樣的特性能夠經過如下方法:

#set( $myval = $foo.bar() )

#callme( $myval )

 

Velocimacro properties

Velocity.properties文件中的某幾行可以使Velocimacros的實現更加靈活。注意更多的內容能夠看Developer Guide

Velocity.properties文件中的velocimacro.libraary:一個以逗號分隔的模板庫列表。默認狀況下,velocity查找惟一的一個庫:VM_global_library.vm。你能夠經過配置這個屬性來指定本身的模板庫。

         Velocity.properties文件中的velocimacro.permissions.allow.inline屬性:有兩個可選的值true或者false,經過它能夠肯定Velocimacros是否能夠被定義在regular template內。默認值是ture――容許設計者在他們本身的模板中定義Velocimacros

         Velocity.properties文件中的velocimacro.permissions.allow.inline.replace.global屬性有兩個可選值truefalse,這個屬性容許使用者肯定inlineVelocimacro定義是否能夠替代全局Velocimacro定義(好比在velocimacro.library屬性中指定的文件內定義的Velocimacro)。默認狀況下,此值爲false。這樣就阻止本地Velocimacro定義覆蓋全局定義。

         Velocity.properties文件中的velocimacro.permissions.allow.inline.local.scale屬性也是有truefalse兩個可選值,默認是false。它的做用是用於肯定你inline定義的Velocimacros是否僅僅在被定義的template內可見。換句話說,若是這個屬性設置爲true,一個inline定義的Velocimacros只能在定義它的template內使用。你可使用此設置實現一個奇妙的VM竅門:a template can define a private implementation of the second VM that will be called by the first VM when invoked by that template. All other templates are unaffected

Velocity.properties文件中的velocimacro.context.localscope屬性有truefalse兩個可選值,默認值爲false。當設置爲true時,任何在Velocimacro內經過#set()context的修改被認爲是針對此velocimacro的本地設置,而不會永久的影響內容。

         Velocity.properties文件中的velocimacro.library.autoreload屬性控制Velocimacro庫的自動加載。默認是false。當設置爲ture時,對於一個Velocimacro的調用將自動檢查原始庫是否發生了變化,若是變化將從新加載它。這個屬性使得你能夠不用從新啓動servlet容器而達到從新加載的效果,就像你使用regular模板同樣。這個屬性可使用的前提就是resource loader緩存是off狀態(file.resource.loader.cache = false)。注意這個屬性其實是針對開發而非產品的。

 

Velocimacro Trivia

Velocimacro必須被定義在他們被使用以前。也就是說,你的#macro()聲明應該出如今使用Velocimacros以前。

特別要注意的是,若是你試圖#parse()一個包含#macro()的模板。由於#parse()發生在運行期,可是解析器在parsetiem決定一個看似VM元素的元素是不是一個VM元素,這樣#parse()-ing一組VM聲明將不按照預期的樣子工做。爲了獲得預期的結果,只須要你簡單的使用velocimacro.library使得Velocity在啓動時加載你的VMs

 

Escaping VTL directives

VTL directives can be escaped with 「\」號,使用方式跟VTLreference使用逃逸符的格式差很少。

## #include( "a.txt" ) renders as <contents of a.txt>

#include( "a.txt" )

 

## \#include( "a.txt" ) renders as \#include( "a.txt" )

\#include( "a.txt" )

 

## \\#include ( "a.txt" ) renders as \<contents of a.txt>

\\#include ( "a.txt" )

在對在一個directive內包含多個script元素的VTL directives使用逃逸符時要特別當心(好比在一個if-else-end statement內)。下面是VTLif-statement的典型應用:

#if( $jazz )

    Vyacheslav Ganelin

#end

若是$jazzture,輸出將是:

Vyacheslav Ganelin

若是$jazzfalse,將沒有輸出。使用逃逸符將改變輸出。考慮一下下面的狀況:

\#if( $jazz )

    Vyacheslav Ganelin

\#end

如今不管$jazztrue仍是false,輸出結果都是:

#if($ jazz )

     Vyacheslav Ganelin

 #end

事實上,因爲你使用了逃逸符,$jazz根本就沒有被解析爲boolean型值。在逃逸符前使用逃逸符是合法的,例如:

\\#if( $jazz )

   Vyacheslav Ganelin

\\#end

以上程序的顯示結果爲:

\ Vyacheslav Ganelin

\

         爲了方便理解,注意到 #if(arg)當新一行的結束(return)在輸出中會省略新行。所以,#if()塊是接着第一個‘\’,顯示來自在#if()前面的‘\\’。最後的‘\’在跟文本不一樣的行,由於那裏有新的一行在‘Ganelin’後面,因此最後‘\\’在#end 的前面。

         可是若是$jazzfalse,那麼將沒有輸出。注意:事情也有例外,若是script elements 沒有徹底的逃避。

\\\#if( $jazz )

    Vyacheslave Ganelin

\\#end

         在這裏#if 已經逃避了,可是#end沒有,有太多的#end 的產生解析錯誤。

VTLFormatting issues

儘管在此用戶手冊中VTL一般都開始一個新行,以下所示:

#set( $imperial = ["Munetaka","Koreyasu","Hisakira","Morikune"] )

#foreach( $shogun in $imperial )

    $shogun

#end

         可是像下面這種寫法也是能夠的:

Send me #set($foo = ["$10 and ","a cake"])#foreach($a in $foo)$a #end please.

         上面的代碼能夠被改寫爲:

Send me

#set( $foo = ["$10 and ","a cake"] )

#foreach( $a in $foo )

$a

#end

please.

或者

Send me

#set($foo       = ["$10 and ","a cake"])

                 #foreach           ($a in $foo )$a

         #end please.

每一種的輸出結果將同樣。

 

 

其餘特性和雜項

math

在模板中可使用Velocity內建的算術函數,如:加、減、乘、除。下面的等式分別是:加、減、乘、除:

#set( $foo = $bar + 3 )

#set( $foo = $bar - 4 )

#set( $foo = $bar * 6 )

#set( $foo = $bar / 2 )

當執行除法時將返回一個Integer類型的結果。而餘數你可使用%來獲得:

#set( $foo = $bar % 5 )

Velocity內使用數學計算公式時,只能使用像-n,-2,-1,0,1,2,n這樣的整數,而不能使用其它類型數據。當一個非整型的對象被使用時它將被logged而且將以null做爲輸出結果。

 

Range Operator

Range operator能夠被用於與#set#foreach statement聯合使用。對於處理一個整型數組它是頗有用的,Range operator具備如下構造形式:

[n..m]

mn都必須是整型,而m是否大於n則可有可無。例子:

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

 

Fourth example:

[1..3]

產生如下輸出:

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中有效。

         網頁設計者使用標準尺寸製做表格,可是某時候會沒有足夠的數據填入表格,就會發現 range 很是有用。

 

Advanced IssueEscaping and

當一個reference分隔時,而且在它以前有逃逸符時,reference將以特殊的方式處理。注意這種方式與標準的逃逸方式時不一樣的。對照以下:

#set( $foo = "bar" )

$\!foo

$\!{foo}

$\\!foo

$\\\!foo

         這將顯示爲:

$!foo

$!{foo}

$\!foo

$\\!foo

         \  $ 前面跟逃避規則相比較;

\$foo

\$!foo

\$!{foo}

\\$!{foo}

         這將顯示爲:

\$foo

\$!foo

\$!{foo}

\bar

 

Velocimacro雜記

         這章節是一個小型涉及Velocimacros的常見問題解答。這章節會隨時間的變化而變化,因此它的做用有時是檢驗新的信息。

         注意:在這章節'Velocimacro'簡稱爲‘VM’。

 

1.        我能用一個標識或者另外的VM 做爲一個VM的參數嗎?

例如:#center ( #bold( 「hello」 ) )

 

答:不能夠。一個directive的參數使用另一個directive是不合法的。

可是,仍是有些事情你能夠做的。最簡單的方式就是使用雙引號,因此你能夠這樣作:

#set($stuff = "#bold('hello')" )

#center( $stuff )

         上面的格式也能夠縮寫爲一行:

#center( "#bold( 'hello' )" )

         請注意在下面的例子中參數被evaluatedVelocimacro內部,而不是在calling level。例子:

 

#macro( inner $foo )

  inner : $foo

#end

 

#macro( outer $foo )

   #set($bar = "outerlala")

   outer : $foo

#end

 

#set($bar = 'calltimelala')

#outer( "#inner($bar)" )

 

輸出結果爲:

Outer : inner : outerlala

         由於#inner($bar)的賦值發生在#outer(),因此$bar的值在#outer()賦給的。

記住Veloctiy的特性:參數的傳遞是By Name的。例如:

#macro( foo $color )

  <tr bgcolor=$color><td>Hi</td></tr>

  <tr bgcolor=$color><td>There</td></tr>

#end

 

 

#foo( $bar.rowColor() )

         以上代碼將致使rowColor()方法兩次調用,而不是一次。爲了不這種現象的出現,咱們能夠按照下面的方式執行:

#set($color = $bar.rowColor())

#foo( $color )

 

2.我能經過#parse()登記velocimacros嗎?

 

答:目前,Velocimacros必須在第一次被模板調用前被定義。這就意味着你的#macro()聲明應該出如今使用Velocimacros以前。

若是你試圖#parse()一個包含#macro() directive的模板,這一點是須要牢記的。由於#parse()發生在運行期,可是解析器在parsetiem決定一個看似VM元素的元素是不是一個VM元素,這樣#parse()-ing一組VM聲明將不按照預期的樣子工做。爲了獲得預期的結果,只須要你簡單的使用velocimacro.library使得Velocity在啓動時加載你的VMs

 

3.什麼是velocimacro自動加載?

 

答:velocimacro.library.autoreload是專門爲開發而非產品使用的一個屬性。此屬性的默認值是false

<type>.resource.loader.cache = false 連同一塊兒設爲true ()(<type>是你用的資源器,例如‘file’),當你編譯它們的時候Velocity引擎會自動重載那些在你的velocimacro庫文件中的修改,因此你不用servlet引擎(或者應用程序)或者其餘竅門來使你的velocimacros重載。

         這裏有一個簡單的屬性配置。

   file.resource.loader.path = templates

   file.resource.loader.cache = false

   velocimacro.library.autoreload = true

    不要在你的做品中出現上述的配置

 

 

字符串串聯

開發人員最常問的問題是我如何做字符拼接?在java中是使用號來完成的。

VTL裏要想實現一樣的功能你只須要將須要聯合的reference放到一塊兒就好了。例如:

      #set( $size = "Big" )

       #set( $name = "Ben" )

 

      The clock is $size$name.

   輸出結果將是:The clock is BigBen.。更有趣的狀況是:

      #set( $size = "Big" )

      #set( $name = "Ben" )

 

      #set($clock = "$size$name" )

 

      The clock is $clock.

   

上例也會獲得一樣的結果。最後一個例子,當你但願混合固定字段到你的reference時,你須要使用標準格式:

      #set( $size = "Big" )

      #set( $name = "Ben" )

 

      #set($clock = "${size}Tall$name" )

 

      The clock is $clock.

   

輸出結果是:The clock is BigTallBen.。使用這種格式主要是爲了使得$size不被解釋爲$sizeTall

 

 本文轉載自:http://www.cnblogs.com/alllearning/archive/2009/12/21/1628676.html

相關文章
相關標籤/搜索