Velocity 文檔(1)

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能爲我們做什麼? 

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


Velocity Template Language(VTL)介紹 
        VTL意味着提供最簡單、最容易並且最整潔的方式合併頁面動態內容。 
        VTL使用引用(references)來在web site內嵌套動態內容。一個變量就是一種類型的reference。變量是某種類型的refreence。它可以指向java代碼中定義的對象,或者在當前頁面內使用VTL statement定義的變量。下面是一個VTL statement的例子,它可以被嵌套到HTML代碼中: 
1 #set ( $a = “Velocity” )

和所有的VTL statement一樣,這個statement以#字符開始並且包含一個directive:set。當一個在線用戶請求你的頁面時,Velocity Templating Engine將查詢整個頁面以便發現所有#字符,然後確定哪些是VTL statement,哪些不需要VTL作任何事情。 #字符後緊跟一個directive:set時,這個set directive 使用一個表達式 (使用一對圓括號`(` , `)` 封閉) 分配一個值給變量$a。變量被列在左邊,而它的值被列在右邊,最後他們之間使用=號分割。

記住以下的規則: 使用$字符開始的references用於得到什麼;使用#字符開始的directives用於作些什麼。

  
        一旦某個變量被分配了一個值,那麼你就可以在HTML文件的任何地方引用它。在下面的例子中,一個值被分配給$foo變量,並在其後被引用。 
1 <html>
2     <body>
3         #set ( $foo = “Velocity” )
4         Hello $foo World!
5     </body>
6 </html>

上面的實現結果是在頁面上打印“Hello Velocity World!” 

        爲了使包含VTL directives的statement更具有可讀性,我們建議在新行開始每個VTL statement,儘管你不是必須這麼作。Set directive將在後面詳細描述。

註釋

單行註釋: 
1 ## This is a single line comment.
多行註釋: 
1   #*
2    Thus begins a multi-line comment. Online visitors won’t
3    see this text because the Velocity Templating Engine will
4 ignore it.
5   *#


文檔格式:  
1 #**
2    This is a VTL comment block and
3    may be used to store such information
4 as the document author and versioning
5    information:
6    @version 5
7    @author
8   *#

References

        在VTL中有三種類型的references:變量(variables)、屬性(properties)、方法(methods)。

        作爲一個使用VTL的頁面設計者,你和你的工程師必須就references的名稱達成共識,以便你可以在你的template中使用它們。

        Everything coming to and from a reference被作爲一個String對象處理。如果有一個對象$foo是一個Integer對象,那麼Velocity將調用它的toString()方法將這個對象轉型爲String類型。 
    變量  
         格式要求同java。 
    屬性  
         例子:  
1 $customer.Address
2 $purchase.Total
          其中$customer.Address有兩種含義。它既可以表示查找hashtable對象customer中以Address爲關鍵字的值, 也可以表示調用customer對象的getAddress()方法。當你的頁面被請求時,Velocity將確定以上兩種方式選用那種,然後返回適當的值。 

     方法 

        一個方法就是被定義在java中的一段代碼,並且它有完成某些有用工作的能力,例如一個執行計算和判斷條件是否成立、滿足等。方法是一個由$開始並跟隨VTL標識符組成的References,一般還包括一個VTL方法體。例如:

1 $customer.getAddress()
2 $purchase.getTotal()
3 $page.setTitle( “My Home Page” )
4 $person.setAttributes( [“Strange”, “Weird”, “Excited”] )

前兩個例子$customer.getAddress()和$purchase.getTotal()看起來挺想上面的屬性$customer.Address 和 $purchase.Total。如果你覺得他們之間有某種聯繫的話,那你是正確的;因爲VTL屬性可以作爲VTL方法的縮寫。$customer.Address屬性和使用$customer.getAddress()方法具有相同的效果。如果可能的話使用屬性的方式是比較合理的。屬性和方法的不同點在於你能夠給一個方法指定一個參數列表 

Velocity利用了很多java規範以方便了設計人員的使用。例如

 $foo.getBar() 等同於 $foo.Bar 等同於 ${foo.Bar}
 $data.getUser(“jon”) 等同於 $data.User(“jon”) 等同於 ${data.User("join")} 
 $data.getRequest().getServerName() 等同於 $data.Request.ServerName 等同於 ${data.Request.ServerName}
 
需要明確的是VTL中不會將reference解釋爲對象的實例變量。例如:$foo.Name將被解釋爲Foo對象的getName()方法(假如$foo所引用的對象不是Hashtale對象),而不是Foo對象的Name實例變量。

    正式reference標記

        reference的正是格式如下: 
1 ${mudSlinger}        ##變量
2 ${customer.Address}    ##屬性
3 ${purchase.getTotal()}    ##方法

但非正式格式更常見,但是有時還是使用正式格式比較好。例如:你希望通過一個變量$vice來動態的組織一個字符串: 
1 Jack is a $vicemaniac.

本來用意是是引用變量$vice,現在卻變成了$vicemaniac,這樣Veloctiy就不知道您到底要什麼了。所以在這種情況下應該使用正式格式書寫:   
1 Jack is a ${vice}maniac

現在Velocity知道你希望引用的變量是$vice而不是$vicemaniac, 模板被渲染後的結果爲: 
Quiet reference notation 

     關於空值(null)的處理

當一個變量沒有被定義或爲空值(null) , velocity模板會將該變量名連同美元符號一起輸出。考慮如下的html片段:

1 <input type=”text” name=”email” value=”$email” />

當頁面的form被初始加載時,變量$email還沒有值,這時你肯定是希望它能夠顯示一個空字符串("")來代替$email這樣的字符串,那麼就需要使用quiet reference notation,即$!標記
1 <input type=”text” name=”email” value=”$!email”/>

 當然 使用正式的quiet格式會更好: 
1 <input type=”text” name=”email” value=”$!{email}”/>

     關於特殊字符的處理 
        Velocity使用特殊字符$和#來幫助它工作,所以如果要在template裏使用這些特殊字符要格外小心。  
        在VTL中, 像$2.5這樣的標識符不會被認爲是一個reference,因爲VTL中的reference總是以一個大寫或者小寫的字母開始. 
        VTL中使用“\”作爲轉義符 
        例如:  
1 #set( $email = “foo” )
2 $email
3 \$email
4 \\$email
5 \\\$email

將被渲染爲: 
  foo 
  $email 
  \foo 
  \\$email 
如果email變量沒有被定義則 
1 $email
2 \$email
3 \\$email
4 \\\$email

將被渲染爲: 
  $email 
  \$email 
  \\$email 
  \\\$email 
  
    指令(Directives) 
        reference允許設計者使用動態的內容,而directive使得你可以控制顯示邏輯,從而達到期望的顯示效果。 
          #set 指令 
        #set directive被用於設置一個reference的值。例如:    
1 #set ( $primate = “monkey” )
2 #set ( $customer.Behavior = $primate )

賦值左側的(LHS)必須是一個變量或者屬性reference。右側(RHS)可以是以下類型中一種: 
  變量引用(variable reference) 
  字符串字面值(String literal) 
  屬性引用(property reference) 
  方法調用(method reference) 
   數字字面值( number literal) 
  數組列表(Array List) 
下面是應用各種類型的RHS的例子: 
1 #set ( $monkey = $bill )                 ## 變量引用(variable reference)
2 #set ( $monkey.Friend = “monica” )       ##字符串字面值(String literal)
3 #set ( $monkey.Blame = $whitehouse.Leak )## 屬性引用(property reference)
4 #set ( $monkey.Plan = $spindoctor.weave($web) )##方法調用(method reference)
5 #set ( $monkey.Number = 123 )                    ## 數字字面值( number literal)
6 #set ( $monkey.Say = [“Not”, $my, “fault”] )        ##數組列表(Array List)

注意:最後一個例子的取值方法爲:$monkey.Say.get(0) 
RHS也可以是一個簡單的算術表達式: 
1 #set ( $value = $foo + 1 )
2 #set ( $value = $bar -1 )
3 #set ( $value = $foo * $bar )
4 #set ( $value = $foo / $bar )

        如果你的RHS是一個null,VTL的處理將比較特殊:它將指向一個已經存在的reference,這對初學者來講可能是比較費解的。例如: 
1 #set ( $resut = $query.criteria(“name”) )
2 The result of the first query is $result
3 #set ( $resut = $query.criteria(“address”) )
4 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 
再看一個例子: 
1 #set( $criteria = ["name", "address"] )
2 #foreach( $criterion in $criteria )
3     #set( $result = $query.criteria($criterion) )
4     #if( $result )
5       Query was successful
6     #end
7 #end

打印的結果將顯示兩次查詢結果都成功了。

        爲什麼會出現這種現象呢?其實當某個變量被賦值後,它就被保存到Velocity的context(added to the context),並且buhui不能被設置回null(removed from the context)。 

        爲了解決以上問題我們可以通過預先定義的方式:

1 #set( $criteria = [“name”, “address”] )
2 #foreach( $criterion in $criteria )
3     #set( $result = false )
4     #set( $result = $query.criteria( $criterion ) )
5     #if( $result )
6       Query was successful
7     #end
8 #end


         關於 字符串字面值(String Literals ) 
      當你使用#set 指令時,如果把字符串字面值(String literal)封閉在一對雙引號內, 比如     
1 #set ( $directoryRoot = “www” )
2 #set ( $templateName = “index.vm” )
3 #set ( $template = “$directoryRoot/$tempateName” )
4 $template

則渲染的結果爲 

      www/index.vm

但是,當字符串字面值(String Literal)被封裝在單引號內時,它將不被解析

1 #set ( $foo = “bar” )
2 $foo
3 #set ( $blargh = ‘$foo’ )
4 $blargh

  結果: 
    bar 
    $foo 

這個特性可以通過修改velocity.properties文件的屬性設置 

stringliterals.interpolate = false 

來改變上面的特性失效。


原文鏈接:http://my.oschina.net/aiguozhe/blog/39553

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章