(1)為什么要使用模版語言?
在服務器端可以使用 Velocity 處理模板和生成的動態內容(HTML、XML等)。這和 JSP 技術的目標非常接近。但是,JSP 模型可以毫無阻礙地訪問底層的 Servlet API 和 Java 編程語言。它基本上是一種在很大程度上開放的訪問模型。而作為一種完全自包含的模板引擎和腳本解釋器,Velocity 擁有完全封閉的模型。任何針對系統和/或 Java 編程語言的訪問都必須明確地啟用。默認情況,Velocity 模板中不能訪問 Java 編程語言的任何方面。這種封閉的模型使 Velocity 能夠提供分離的模板表示層,與任何應用程序業務邏輯或者數據管理代碼清晰地划分開。從而保證了web site 的長期可維護性.
第一次解釋jsp需要經過轉換成java代碼,再編譯成class文件等步驟,而velocity則在速度上更快,因為它不需要經過像解釋jsp頁面那么多的步驟,其次velocity也可以用作其它實現的模板技術,像我在項目中就遇到過使用velocity來作為郵件的模板,而jsp顯然做不到這樣的功能。
拓展:在java領域,表現層技術主要有三種:jsp、freemarker、velocity。
jsp是大家最熟悉的技術
優點:
1、功能強大,可以寫java代碼
2、支持jsp標簽(jsp tag)
3、支持表達式語言(el)
4、官方標准,用戶群廣,豐富的第三方jsp標簽庫
5、性能良好。jsp編譯成class文件執行,有很好的性能表現
缺點:沒有明顯缺點,非要挑點骨頭就是,由於可編寫java代碼,如使用不當容易破壞mvc結構。
velocity是較早出現的用於代替jsp的模板語言
優點:
1、不能編寫java代碼,可以實現嚴格的mvc分離
2、性能良好,據說比jsp性能還要好些
3、使用表達式語言,據說jsp的表達式語言就是學velocity的
缺點:
1、不是官方標准 2、用戶群體和第三方標簽庫沒有jsp多 3、對jsp標簽支持不夠好
freemarker 也是一種模版引擎語言
優點:
1、不能編寫java代碼,可以實現嚴格的mvc分離
2、性能非常不錯
3、對jsp標簽支持良好
4、內置大量常用功能,使用非常方便
5、宏定義(類似jsp標簽)非常方便
6、使用表達式語言
缺點:
1、不是官方標准 2、用戶群體和第三方標簽庫沒有jsp多
綜合對比:
1、性能。velocity應該是最好的,其次是jsp,普通的頁面freemarker性能最差(雖然只是幾毫秒到十幾毫秒的差距)。但是在復雜頁面上(包含大量判斷、日期金額格式化)的頁面上,freemarker的性能比使用tag和el的jsp好。
2、freemarker宏定義比jsp tag方便,內置大量常用功能,比如html過濾,日期金額格式化等等,支持jsp標簽。且freemarker和velovity一樣,作為模版語言,都可以實現嚴格的mvc分離。
(2)Velocity模版語言(VTL)使用詳解
① VTL變量聲明
所有的VTL statement 都是以#開頭,且包含一個指示符,當客戶訪問你的頁面時, the Velocity Templating Engine 將搜索頁面中的所有# 符號,如果確定這是一個VTL 聲明時就按一定規則處理動態內容, 符號#僅僅只是表明這可能是一個VTL 聲明.記住以下的規則:
使用$字符開始的references用於得到什么;使用 #字符開始的directives用於作些什么。
在下面的例子中,一個值被分配給$foo變量,並在其后被引用。
<html>
<body>
#set ( $foo = “Velocity” )
Hello $foo World!
</body>
</html>
上面的實現結果是在頁面上打印“Hello Velocity World!”
② 注釋語法
單行注釋:## 內容
多行注釋:#* 內容 *#
文檔格式:#** 內容 *#
③ 正式引用標記
${mudSlinger} 變量
${customer.Address} 屬性
${purchase.getTotal()} 方法
如果寫成如下的語法格式,當值為null的時候會原樣輸出字符串
$mudSlinger 變量
$customer.Address 屬性
$purchase.getTotal() 方法
所以盡量使用正式的標記或者可以寫成如下的方式:
$!mudSlinger 變量
$!customer.Address 屬性
$!purchase.getTotal() 方法
也可以一同使用
$!{mudSlinger} 變量
$!{customer.Address} 屬性
$!{purchase.getTotal()} 方法
拓展:$customer.address 引用時,查找順序是:
1.getaddress() 2. getAddress() 3. get(“address”) 4. isAddress()
④ 如何在velocity中使用特殊字符?
$字符:貨幣字符
在VTL中使用$2.5這樣的貨幣標識是沒有問題得的,VTL不會將它錯認為是一個reference,因為VTL中的reference總是以一個大寫或者小寫的字母開始。但還是要明白,VTL中使用“\”作為逃逸符。如:\$name將會輸出$name字符串。
⑤ 常用基礎語法
1)條件語句
#if ( $foo ) 1 #else 2 #end
上例中的條件語句將在以下兩種條件下成立:
1.$foo是一個boolean型的變量,且它的值為true
2.$foo變量的值不為null
#if( $foo < 60 ) 完蛋了 #elseif( $foo == 60 ) 萬幸 #else 浪費 #end
2)循環語句
#foreach ( $product in $allProducts )
這是第$velocityCount次循環,值為: $product
#end
每次循環$allProducts中的一個值都會賦給$product變量。
$velocityCount 變量的名字是Velocity默認的名字,你也可以通過修改velocity.properties文件來改變它。默認情況下,計數從“1”開始,但是你 可以在velocity.properties設置它是從“1”還是從“0”開始。下面就是文件中的配置:
directive.foreach.counter.name = velocityCount
directive.foreach.counter.initial.value = 1
現在我們假設$allProducts是一個Hashtable,如果你希望得到它的key應該像下面這樣:
<ul>
#foreach ( $key in $allProducts.keySet() )
<li>Key: $key -> Value: $allProducts.get($key) </li>
#end
</ul>
3) 關系、邏輯運算符
相等 == 不等 != 且 && 或|| 非 !
4) include
#include script element允許模板設計者引入本地文件。被引入文件的內容將不會通過模板引擎被render。為了安全的原因,被引入的本地文件只能在TEMPLATE_ROOT目錄下。
#inclued ( “one.txt” )
如果您需要引入多個文件,可以用逗號分隔就行:
#include ( “one.gif”, “two.txt”, “three.htm” )
在括號內可以是文件名,但是更多的時候是使用變量的:
#inclue ( “greetings.txt”, $seasonalstock )
5) 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是可以遞歸調用的
6) Range Operator
#foreach ( $bar in [2..-2] ) $bar #end
結果:2 1 0 -1 -2
#set ( $arr = [0..1] )
#foreach ( $i in $arr ) $i #end
結果:0 1
7) 內置對象
velocity內置了一些對象,在vm模版里可以直接調用,列舉如下:
$request、$response、$session,另外,模板內還可以使用 $msg內的消息工具訪問 Struts 的國際化資源,達到簡便實現國際化的方法。
8) 四則運算
直接進行四則運算將會默認為字符串連接,因此運算應該是如下的方式解決。
如果$foo=2.則$foo + 1 結果是21,而不是3.
需要先#set ( $value = $foo + 1 ) ,然后$value 結果才是3
9) 解析步驟
當Velocity應用在應用程序時,一般分一下幾步:
初始化Velocity==>創建context對象==>添加數據到context==>選擇模板==>合並模板和數據,產生輸出頁面
10) velocity.properties文件詳解(在spring集成的時候主要是配置在prop標簽中)
1. tools.view.servlet.error.template = error.vmzd
處理錯誤信息的模板路徑
2. tools.view.servlet.layout.directory = /WEB-INF/layout/ 所有布局文件的默認路徑
3. tools.view.servlet.layout.default.template = defauzlt.vm
默認的布局文件
4. #模板編碼:
input.encoding=ISO-8859-1 //模板輸入編碼
output.encoding=ISO-8859-1 //模板輸出編碼
5. velocimacro.library=/WEB-INF/vm/macro.vm,/WEB-INF/vm/tuanmacro.vm
是一個逗號分隔的所有Velocimacro 模板庫的列表
(3)如何把VTL集成到spring的項目框架中?
① 需要的jar包
commons-collections.jar
velocity-1.5.jar
velocity-dept.jar
velocity-tool-view1.4.jar
下載地址:http://jakarta.apache.org/velocity/
② 引入Velocity包
在application-context.xml配置文件里配置VelocityConfigurer,當然也可以在dispatcher-servlet(application-springmvc.xml)里面配置,這完全取決於你自己的想法。
下面的配置使Spring能夠知道我們的模板文件是放在哪里的
<bean id="velocityConfigurer" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer"> <property name="resourceLoaderPath" value="/WEB-INF/views"/> </bean>
在dispatcher-servlet里配置VelocityViewResolver
下面的配置則是針對一個模板文件使用的是什么后綴。
<bean id="velocityViewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver"> <property name="suffix" value=".vm"/> </bean>
本項目例子:
格式化時間:
$date.format('yyyy-MM-dd HH:mm:ss',$element.createTime)