Velocity用戶手冊(比較完整的資料)

 
Velocity用戶手冊
主 題:Velocity用戶手冊
創建人:王藝
郵 箱:[email protected]
QQ號:179985017
創建時間:2003年8月9日星期六
英文源文件:http://jakarta.apache.org/velocity/user-guide.html
聲明:
 由於個人英文能力有限,很多地方翻譯的可能不清楚,甚至有些地方翻譯的與原文不符。如您在閱讀中發現有錯誤之處還請及時指正,謝謝。

目錄
1. About this Guide
2. What is Velocity?
3. What can Velocity do for me?
1. The Mud Store example
4. Velocity Template Language (VTL): An Introduction
5. Hello Velocity World!
6. Comments
7. References
1. Variables
2. Properties
3. Methods
8. Formal Reference Notation
9. Quiet Reference Notation
10. Getting literal
1. Currency
2. Escaping Valid VTL References
11. Case Substitution
12. Directives
1. Set
2. String Literals
3. If-Else Statements
1. Relational and Logical Operators
4. Foreach Loops
5. Include
6. Parse
7. Stop
8. Velocimacros
2. Escaping VTL Directives
3. VTL: Formatting Issues
4. Other Features and Miscellany
1. Math
2. Range Operator
3. Advanced Issues: Escaping and !
4. Velocimacro Miscellany
5. String Concatenation
5. Feedback
 

Velocity是什麼?
Velocity是一個基於java的模板引擎(template engine)。它允許任何人僅僅簡單的使用模板語言(template language)來引用由java代碼定義的對象。
當Velocity應用於web開發時,界面設計人員可以和java程序開發人員同步開發一個遵循MVC架構的web站點,也就是說,頁面設計人員可以只關注頁面的顯示效果,而由java程序開發人員關注業務邏輯編碼。Velocity將java代碼從web頁面中分離出來,這樣爲web站點的長期維護提供了便利,同時也爲我們在JSP和PHP之外又提供了一種可選的方案。
Velocity的能力遠不止web站點開發這個領域,例如,它可以從模板(template)產生SQL和PostScript、XML,它也可以被當作一個獨立工具來產生源代碼和報告,或者作爲其他系統的集成組件使用。Velocity也可以爲Turbine web開發架構提供模板服務(template service)。Velocity+Turbine提供一個模板服務的方式允許一個web應用以一個真正的MVC模型進行開發。

Velocity能爲我們作什麼?
The Mud Store Example 
假設你是一家專門出售Mud的在線商店的頁面設計人員,讓我們暫且稱它爲"在線MUD商店"。你們的業務很旺,客戶下了各種類型和數量的mud訂單。他們都是通過輸入用戶名和密碼後才登陸到你的網站,登陸後就允許他們查看訂單併購買更多的mud。現在,一種非常流行的mud正在打折銷售。另外有一些客戶規律性的購買另外一種也在打折但是不是很流行的Bright Red Mud,由於購買的人並不多所以它被安置在頁面的邊緣。所有用戶的信息都是被跟蹤並存放於數據庫中的,所以某天有一個問題可能會冒出來:爲什麼不使用velocity來使用戶更好的瀏覽他們感興趣的商品呢?
Velocity使得web頁面的客戶化工作非常容易。作爲一個web site的設計人員,你希望每個用戶登陸時都擁有自己的頁面。
你會見了一些公司內的軟件工程師,你發現他們每個人都同意客戶應該擁有具有個性化的信息。那讓我們把軟件工程師應該作的事情發在一邊,看一看你應該作些什麼吧。
你可能在頁面內嵌套如下的VTL聲明:
<html>
<body>
Hello  $customer.Name!
<table>
#foreach( $mud  in  $nudsOnSpecial )
    #if ( $customer.hasPurchased( $mud )  )
        <tr>
            <td>
                $flogger.getPromo( $mud )
            <td>
        <tr>
    #end
#end
</table>

Velocity Template Language(VTL):AN introduction
VTL意味着提供最簡單、最容易並且最整潔的方式合併頁面動態內容。
VTL使用references來在web site內嵌套動態內容,一個變量就是一種類型的reference。變量是某種類型的refreence,它可以指向java代碼中的定義,或者從當前頁面內定義的VTL statement得到值。下面是一個VTL statement的例子,它可以被嵌套到HTML代碼中:
#set ( $a = "Velocity" )
和所有的VTL statement一樣,這個statement以#字符開始並且包含一個directive:set。當一個在線用戶請求你的頁面時,Velocity Templating Engine將查詢整個頁面以便發現所有#字符,然後確定哪些是VTL statement,哪些不需要VTL作任何事情。
#字符後緊跟一個directive:set時,這個set directive使用一個表達式(使用括號封閉)――一個方程式分配一個值給變量。變量被列在左邊,而它的值被列在右邊,最後他們之間使用=號分割。
在上面的例子中,變量是$a,而它的值是Velocity。和其他的references一樣以$字符開始,而值總是以雙引號封閉。Velocity中僅有String可以被賦值給變量。
記住以下的規則:
使用$字符開始的references用於得到什麼;使用#字符開始的directives用於作些什麼。

Hello Velocity World!
一旦某個變量被分配了一個值,那麼你就可以在HTML文件的任何地方引用它。在下面的例子中,一個值被分配給$foo變量,並在其後被引用。
 <html>
  <body>
      #set ( $foo = "Velocity" )
      Hello $foo World!
  </body>
 </html>
上面的實現結果是在頁面上打印"Hello Velocity World!"
爲了使包含VTL directives的statement更具有可讀性,我們鼓勵你在新行開始每個VTL statement,儘管你不是必須這麼作。Set directive將在後面詳細描述。
註釋
單行註釋:
 ## This is a single line comment.
多行註釋:
 #*
   Thus begins a multi-line comment. Online visitors won't
   see this text because the Velocity Templating Engine will
      ignore it.
 *#
文檔格式:
 #**
   This is a VTL comment block and may be used to store such information as the document author and versioning information:
   @version 5
   @author
 *#
 
References
在VTL中有三種類型的references:變量(variables)、屬性(properties)、方法(methods)。作爲一個使用VTL的頁面設計者,你和你的工程師必須就references的名稱達成共識,以便你可以在你的template中使用它們。
Everything coming to and from a reference被作爲一個String對象處理。如果有一個對象$foo是一個Integer對象,那麼Velocity將調用它的toString()方法將這個對象轉型爲String類型。
 變量                                                                      
 格式要求同java。
 屬性                                                                      
 例子:
  $customer.Address
  $purchase.Total
$customer.Address有兩種含義。它可以表示:查找hashtable對象customer中以Address爲關鍵字的值;也可以表示調用customer對象的getAddress()方法。當你的頁面被請求時,Velocity將確定以上兩種方式選用那種,然後返回適當的值。

方法
一個方法就是被定義在java中的一段代碼,並且它有完成某些有用工作的能力,例如一個執行計算和判斷條件是否成立、滿足等。方法是一個由$開始並跟隨VTL標識符組成的References,一般還包括一個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()方法具有相同的效果。如果可能的話使用屬性的方式是比較合理的。屬性和方法的不同點在於你能夠給一個方法指定一個參數列表。

正式reference標記
reference的正是格式如下:
 ${mudSlinger}    變量
 ${customer.Address}  屬性
 ${purchase.getTotal()}  方法
非正是格式更見常用,但是有時還是使用正是格式比較適合。例如:你希望通過一個變量$vice來動態的組織一個字符串。
Jack is a $vicemaniac.
本來變量是$vice現在卻變成了$vicemaniac,這樣Veloctiy就不知道您到底要什麼了。所以,應該使用正是格式書寫
Jack is a ${vice}maniac
現在Velocity知道變量是$vice而不是$vicemaniac。
Quiet reference notation
例如:
 <input  type="text"  name="email"  value="$email" />
當頁面的form被初始加載時,變量$email還沒有值,這時你肯定是希望它能夠顯示一個blank text來代替輸出"$email"這樣的字段。那麼使用quiet reference notation就比較合適。
 <input  type="text"  name="email"  value="$!email"/>
這樣文本框的初始值就不會是email而是空值了。
正式和quiet格式的reference notation也可一同使用,像下面這樣:
 <input  type="text"  name="email"  value="$!{email}"/>
Getting literal                                                             
Velocity使用特殊字符$和#來幫助它工作,所以如果要在template裏使用這些特殊字符要格外小心。本節將討論$字符。
 貨幣字符                                                                  
在VTL中使用$2.5這樣的貨幣標識是沒有問題得的,VTL不會將它錯認爲是一個reference,因爲VTL中的reference總是以一個大寫或者小寫的字母開始。
Escaping valid VTL reference                                             
VTL中使用"/"作爲逃逸符。
例如:
 #set( $email = "foo" )
 $email
 /$email
 //$email
 ///$email
將render爲:
 foo
 $email
 /foo
 //$email
如果email變量沒有被定義則
 $email
 /$email
 //$email
 ///$email
將被render爲:
 $email
 /$email
 //$email
 ///$email
注意:VTL中未被定義的變量將被認爲是一個字符串,所以以下例子:
 #set( $foo = "gibbous" )
 $moon = $foo
的輸出結果是:
$moon = gibbous
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}
但是,注意VTL中不會將reference解釋爲對象的實例變量。例如:$foo.Name將被解釋爲Foo對象的getName()方法,而不是Foo對象的Name實例變量。
Directives
Reference允許設計者使用動態的內容,而directive使得你可以應用java代碼來控制你的顯示邏輯,從而達到你所期望的顯示效果。
 #set                                                                      
 #set directive被用於設置一個reference的值。例如:
  #set ( $primate = "monkey" )
  #set ( $customer.Behavior = $primate )
賦值左側的(LHS)必須是一個變量或者屬性reference。右側(RHS)可以是以下類型中一種:
  變量reference
  String literal
  屬性reference
  方法reference
  number literal
  ArrayList
下面是應用各種類型的RHS的例子:
 #set ( $monkey = $bill ) ##變量reference
 #set ( $monkey.Friend = "monica" ) ##String literal
 #set ( $monkey.Blame = $whitehouse.Leak )##屬性reference
 #set ( $monkey.Plan = $spindoctor.weave($web) )##方法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是一個null,VTL的處理將比較特殊:它將指向一個已經存在的reference,這對初學者來講可能是比較費解的。例如:
 #set ( $resut = $query.criteria("name") )
 The result of the first query is $result
 #set ( $resut = $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 first query is bill
看看下面的例子:
 #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),它不能被設置回null(removed 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
 String Literals                                                        
 當你使用#set directive,String literal封閉在一對雙引號內。
  #set ( $directoryRoot = "www" )
  #set ( $templateName = "index.vm" )
  #set ( $template = "$directoryRoot/$tempateName" )
  $template
 上面這段代碼的輸出結果爲:www/index.vm
 但是,當string literal被封裝在單引號內時,它將不被解析:
  #set ( $foo = "bar" )
  $foo
  #set ( $blargh = '$foo' )
 結果:
  bar
  $foo
 上面這個特性可以通過修改velocity.properties文件的stringliterals.interpolate = false的值來改變上面的特性是否有效。
條件語句
 if/elseif/else                                                              
當一個web頁面被生成時使用Velocity的#if directrive,如果條件成立的話可以在頁面內嵌入文字。例如:
 #if ( $foo )
  <strong>Velocity!</strong>
 #end
上例中的條件語句將在以下兩種條件下成立:
  $foo是一個boolean型的變量,且它的值爲true
  $foo變量的值不爲null
這裏需要注意一點:Velocity context僅僅能夠包含對象,所以當我們說"boolean"時實際上代表的時一個Boolean對象。即便某個方法返回的是一個boolean值,Velocity也會利用內省機制將它轉換爲一個Boolean的相同值。
如果條件成立,那麼#if和#end之間的內容將被顯示。
#elseif和#else元素可以同#if一同使用。例如:
 #if( $foo < 10 )
  <strong> Go North </strong>
 #elseif( $foo == 10 )
  <strong> Go East </strong>
 #elseif( $foo == 6 )
  <strong> Go South </strong>
 #else
  <strong> Go West </strong>
 #end
注意這裏的Velocity的數字是作爲Integer來比較的――其他類型的對象將使得條件爲false,但是與java不同它使用"=="來比較兩個值,而且velocity要求等號兩邊的值類型相同。
關係、邏輯運算符                                                          
Velocity中使用等號操作符判斷兩個變量的關係。例如:
 #set ( $foo = "deoxyribonucleic acid" )
 #set ( $bar = "ribonucleic acid" )
 #if ( $foo == $foo )
  In this case it's clear they aren't equivalent.So…
 #else
  They are not equivalent and this will be the output.
 #end
Velocity有AND、OR和NOT邏輯運算符。下面是一些例子:
 ## logical AND
 #if( $foo && $bar )
  <strong> This AND that </strong>
 #end
 ## logical OR
 #if ( $foo || $bar )
  <strong>This OR That </strong>
 #end
 ##logical NOT
 #if ( !$foo )
  <strong> NOT that </strong>
 #end
循環                                                                      
 Foreach循環                                                              
 例子:
  <ul>
   #foreach ( $product in $allProducts )
    <li> $product </li>
   #end
  </ul>
 每次循環$allProducts中的一個值都會賦給$product變量。
$allProducts可以是一個Vector、Hashtable或者Array。分配給$product的值是一個java對象,並且可以通過變量被引用。例如:如果$product是一個java的Product類,並且這個產品的名字可以通過調用他的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 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目錄下。
 #inclued ( "one.txt" )
如果您需要引入多個文件,可以用逗號分隔就行:
 #include ( "one.gif", "two.txt", "three.htm" )
在括號內可以是文件名,但是更多的時候是使用變量的:
 #inclue ( "greetings.txt", $seasonalstock )
parse
#parse script element允許模板設計者一個包含VTL的本地文件。Velocity將解析其中的VTL並render模板。
 #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.
 8
 7
 6
 5
 4
 3
 2
 1
 0
 All done with parsefoo.vm!
All done with dofoo.vm!
Stop
#stop script element允許模板設計者停止執行模板引擎並返回。把它應用於debug是很有幫助的。
 #stop
Velocimacros
#macro script element允許模板設計者定義一段可重用的VTL template。例如:
 #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
調用#tablerows Velocimacro:
 #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>
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>
上面VTL將產生如下的輸出:
 <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可以使用以下任何元素作爲參數:
  Reference:任何以$開頭的reference
  String literal:
  Number literal:
  IntegerRange:[1….3]或者[$foo….$bar]
  對象數組:["a","b","c"]
  boolean值:true、false
當將一個reference作爲參數傳遞給Velocimacro時,請注意reference作爲參數時是以名字的形式傳遞的。這就意味着參數的值在每次Velocimacro內執行時纔會被產生。這個特性使得你可以將一個方法調用作爲參數傳遞給Velocimacro,而每次Velocimacro執行時都是通過這個方法調用產生不同的值來執行的。例如:
 #macro ( callme $a )
  $a $a $a
 #end
 #callme( $foo.bar() )
執行的結果是:reference $foo的bar()方法被執行了三次。
如果你不需要這樣的特性可以通過以下方法:
 #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屬性有兩個可選值true和false,這個屬性允許使用者確定inline的Velocimacro定義是否可以替代全局Velocimacro定義(比如在velocimacro.library屬性中指定的文件內定義的Velocimacro)。默認情況下,此值爲false。這樣就阻止本地Velocimacro定義覆蓋全局定義。
Velocity.properties文件中的velocimacro.permissions.allow.inline.local.scale屬性也是有true和false兩個可選值,默認是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屬性有true和false兩個可選值,默認值爲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 "/"號,使用方式跟VTL的reference使用逃逸符的格式差不多。
 ## #include( "a.txt" ) renders as <ontents of a.txt>(註釋行)
 #include( "a.txt" )
 ## /#include( "a.txt" ) renders as /#include( "a.txt" )
 /#include( "a.txt" )
 ## file://#include/ ( "a.txt" ) renders as /<contents of a.txt>
 file://#include/( "a.txt" )
在對在一個directive內包含多個script元素的VTL directives使用逃逸符時要特別小心(比如在一個if-else-end statement內)。下面是VTL的if-statement的典型應用:
 #if ( $jazz )
  Vyacheslav Ganelin
 #end
如果$jazz是ture,輸出將是:
 Vyacheslav Ganelin
如果$jazz是false,將沒有輸出。使用逃逸符將改變輸出。考慮一下下面的情況:
 /#if ( $jazz )
  Vyacheslav Ganelin
 /#end
現在無論$jazz是true還是false,輸出結果都是:
 #if ( $jazz )
  Vyacheslav Ganelin
 #end
事實上,由於你使用了逃逸符,$jazz根本就沒有被解析爲boolean型值。在逃逸符前使用逃逸符是合法的,例如:
 file://#if/ ( $jazz )
  Vyacheslav Ganelin
 file://#end/
以上程序的顯示結果爲:
 / Vyacheslav Ganelin
 /
但是如果$jazz爲false,那麼將沒有輸出。(書上說會沒有輸出,但是我覺得應該還有有"/"字符被輸出。)
VTL:Formatting 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
&nb$name = "Ben" )
 #set ( $clock = "${size}Tall$name" )
 The clock is $clock.
輸出結果是:The clock is BigTallBen.。使用這種格式主要是爲了使得$size不被解釋爲$sizeTall。
($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]
m和n都必須是整型,而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中有效。
Advanced Issue:Escaping and!
當一個reference被"!"分隔時,並且在它之前有逃逸符時,reference將以特殊的方式處理。注意這種方式與標準的逃逸方式時不同的。對照如下:
#set ( $foo = "bar" )
特殊形式 標準格式
Render前 Render後 Render前 Render後
$/!foo $!foo /$foo /$foo
$/!{foo} $!{foo} /$!foo /$!foo
$//!foo $/!foo /$!{foo} /$!{foo}
$///!foo $//!foo file://$!{foo/} /bar
Velocimacro雜記
 Can I user a directive or another VM as an argument to a VM?     
 例如:#center ( #bold( "hello" ) )
 不可以。一個directive的參數使用另外一個directive是不合法的。
 但是,還是有些事情你可以作的。最簡單的方式就是使用雙引號:
  #set ( $stuff = "#bold( 'hello' )" )
  #center ( $stuff )
 上面的格式也可以縮寫爲一行:
  #center ( "#bold( 'hello' ) )
請注意在下面的例子中參數被evaluated在Velocimacro內部,而不是在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
記住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 )
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放到一起就行了。例如:
#set ( $size = "Big" )
#set ( $name = "Ben" )
The clock is $size$name.
輸出結果將是:The clock is BigBen.。更有趣的情況是:
 #set ( $size = "Big" )
 #set ( $name = "Ben" )
 #set ( $clokc = "$size$name" )
 The clock is $clock.
上例也會得到同樣的結果。最後一個例子,當你希望混合固定字段到你的reference時,你需要使用標準格式:
 #set ( $size = "Big" )
 #set (
 
posted 2005-02-25 16:19:00.0
 
 
發佈了19 篇原創文章 · 獲贊 0 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章