整理下Velocity使用方法,整理比較詳細用例
1 Velocity基礎語法
1.1 用戶和開發人員參考文檔
http://velocity.apache.org/engine/releases/velocity-1.7/developer-guide.html
1.2 注釋
1.行級注釋##
2.多行注釋#* *#
1.3 變量定義
使用$開頭的字符串是變量定義,例如$var1, $var2,
1.4 賦值
使用#set為變量賦值,例如
Java代碼
- #set($var1 = 100)
- #set($str="foobar")
- #set($var2 = $var1)
- $var2 ##顯示100
1. #set指令需要使用小括號將賦值語句括起來
2. #set語句后面不要加“;”,否則;將解析到頁面上
3. #set是行級指令,不需要使用#end
1.5 {}含義
假如有一個Velocity變量,例如$abc, 那么$abcdef這種串如何表達它的含義,即變量$abc的值連接def,默認Velocity會認為$abcdef是一個變量,此時需要使用${abc}def來表達它的含義。
1.6 算術運算
1. 運算符: + - * / %
2. 使用#set語句執行算術運算操作
Java代碼
- #set($a = 5)
- #set($b = 4)
- #set($c = 3)
- #set($d = 2)
- #set($e = 7)
- #set($a= $a+$b*$c/$d - 6%$e) ##5+4*3/2-6%7=5
- "Result:" $a
1.7 關系運算
> >= == <= <
1.8 邏輯運算
&& || !
1.9 條件判斷
Java代碼
- #set($var1 = 20)
- #if($va1 >= 100)
- $var1 is greater than or equals 100
- #elseif($va1 >= 50)
- $var1 is betwen [50, 100)
- #elseif($var1 >= 0)
- $var1 is between [0,50)
- #else
- $var1 is negative
- #end
1. #if是條件判斷語句,#if/#else, #if/#elseif/#else 是if/else條件判斷語句
2. if/elseif使用括號括起來
3. #if是塊級指令,因此使用#end顯示指定塊級指令的結束
1.10 循環語句
Java代碼
- #set($array = [1, "Two", 3,"Four"])
- #foreach($i in $array)
- <li>
- The $velocityCount element in the array is $i
- </li>
- #end
1. 數組定義類似於Javascript,用中括號[]括起來,以逗號分隔
2. $velocityCount是Velocity內置屬性,用於指示當前循環的次數,從1開始計算,即第一次循環,它的值是1
3. #foreach in語句用於表示循環,
4. #foreach語句也是塊級語句,需要使用#end來指明語句的結束
1.11 $!的含義
$!var1的含義是如果變量var1存在,則取其值,否則取空,即不顯示,它等價於如下語句
Java代碼
- #set($var1 = 100)
- $!var2 ##show nothing
- $!var1 ##show 100
- #if($var1)
- $var1
- #end
- #if($var2)
- #var2
- #end
1.12 #include指令
#include可以在vm中指定靜態文件,這跟JSP的include標簽的含義一樣,例如
#include("staticHTML.html"),這個staticHTML.html
#include指令默認從classpath開始尋找文件??目前不確定!
1.13 Velocity資源加載器
在#include指令一節說到了include的文件到什么位置進行加載,這個位置與velocity資源加載的配置有關,常用的加載位置包括 webapp資源加載器,文件路徑資源加載器,還有類路徑記載器,在velocity.properties中,添加如下的配置項表示webapp資源加 載器,項目對於web項目的根開始算起
Java代碼
- resource.loader=webapp
- webapp.resource.loader.class=org.apache.velocity.tools.view.WebappResourceLoader
- #relative to the web context, under the same parent directory with WEB-INF
- #that is, vm and WEB-INF are sibling folders
- webapp.resource.loader.path=/vm
其中的webapp是資源加載器的名稱,/vm是web應用的根下面的vm目錄,也就是說,vm目錄和WEB-INF目錄是平級的
Velocity是一個基於java的模板引擎。它允許任何人僅僅簡單的使用模板語言來引用由java代碼定義的對象。
當Velocity應用於web開發時,界面設計人員可以和java程序開發人員同步開發一個遵循MVC架構的web站點,也就是說,頁面設計人員 可以只 關注頁面的顯示效果,而由java程序開發人員關注業務邏輯編碼。Velocity將java代碼從web頁面中分離出來,這樣為web站點的長期維護提 供了便利,同時也為我們在JSP和PHP之外又提供了一種可選的方案。
Velocity基本語法和使用:
1. "#"用來標識Velocity的腳本語句。
如:#set、#if 、#else、#foreach、#end、#include、#parse、#macro等。
2. "$"用來標識一個對象(或理解為PHP的變量)
如:、
user等。
3. "{}"用來明確標識Velocity變量,和普通模版字符串區分開來;
如:${user}‘s age 可以顯示為 riqi's age。
4. "!"強制把不存在的變量顯示為空白。
如:,假如對象為空,則模版中不顯示該變量;如果缺少,則顯示
msg字符串,這是我們不想要的結果。
5. 變量的定義和賦值。不需要指定變量的類型,類似弱類型語言PHP可以隨意指定,在賦值后自動判定變量的類型,如:
#set($username="riqi") ##設置用戶名
#set($age=26) ##設置年齡
6. 數組循環:
#foreach ($user in $users)
$!{user} $!{velocityCount} <br />
#end
可以是、或者,提供了得到循環次數的值:
velocityCount。
7. 語句注釋:
單行注釋:## 單行注釋代碼
多行注釋:#* 多行注釋代碼 *#
8. 模版支持關系和邏輯操作符運算,如:&&、||、! 等
9. 宏定義:#macro ,類似PHP聲明一個函數,其中有函數名稱和參數列表。先定義再調用。
10. 終止命令:#stop,類似PHP的exit(); 停止執行模板引擎並返回。
11. 引入公共模版文件:#include與#parse,它們的差異是:
(1) 與#include不同的是,#parse只能指定單個對象。而#include可以有多個
如果您需要引入多個文件,可以用逗號分隔就行:
#include ("one.gif", "two.txt", "three.htm" )
在括號內可以是文件名,但是更多的時候是使用變量的:
#include ( “greetings.txt”, $seasonalstock )
(2) #include被引入文件的內容將不會通過模板引擎解析;
而#parse引入的文件內容Velocity將解析其中的velocity語法並移交給模板,意思就是說相當與把引入的文件copy到文件中。
#parse是可以遞歸調用的。
12. 轉義字符'\'.
這個和其它語言沒有差異,假如:那么,表示輸出
user字符串,\\$user表示輸出\riqi。
13. Velocity內置了一部分java對象 如:、
response、$session等,在vm模版里可以直接調用。
------------------------------------------------------------------------------------
細節整理:
1. Velocity判斷某個變量是否為空的方式:
1 |
#if($!變量名)……#else……#end |
或者:
1 |
#if("" == $!varName)……#else……#end |
2 Velocity與Java互操作
Velocity出現的目的用於簡化基於MVC的web應用開發,用於替代JSP標簽技術,那么Velocity如何訪問Java代碼.本篇繼續以Velocity三http://bit1129.iteye.com/blog/2106142中的例子為基礎,
2.1 POJO
Java代碼
- package com.tom.servlets;
- public class User {
- private String name;
- private String passwd;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public String getPasswd() {
- return passwd;
- }
- public void setPasswd(String passwd) {
- this.passwd = passwd;
- }
- }
2.2 Service
Java代碼
- package com.tom.servlets;
- public class UserService {
- public User get(String userId) {
- User user = new User();
- user.setName("tom");
- user.setPasswd("tom_pwd");
- return user;
- }
- public User get(Long userId) {
- User user = new User();
- user.setName("Jack");
- user.setPasswd("Jack");
- return user;
- }
- public void save() {//用於測試,vm是否可以調用無參數的方法
- System.out.println("save is called");
- }
- }
2.3 Servlet代碼
Java代碼
- package com.tom.servlets;
- import org.apache.velocity.Template;
- import org.apache.velocity.context.Context;
- import org.apache.velocity.tools.view.VelocityViewServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- public class TestVelocityViewServlet extends VelocityViewServlet {
- @Override
- protected Template handleRequest(HttpServletRequest request, HttpServletResponse response, Context ctx) {
- UserService userService = new UserService();
- ctx.put("userService" , userService);//把userService對象設置到Context中
- return getTemplate("obj.vm");
- }
- }
2.4 vm代碼
Html代碼
- <!--obj.vm-->
- <html>
- <body>
- <p>$userService</p> ##call userService's toString method
- #set($user = $userService.get(0)) ##When call the java method on its object, only string typed parameters can be accepted
- <p>$user.name</p> ##print #$user.name as it is, because $user can't be resolved
- <p>$user.getName()</p> ##Equivalent with $user.name
- #set($user = $userService.get("0"))
- <p>$user.name</p> ##print $$user.name as it is, because $user can't be resolved
- <p>$user.getName()</p> ##Equivalent with $user.name
- <p>$user.save()</p> ##$user.save can't be resolved,so vm can't resolve method that takes no parameter
- </body>
- </html>
2.5 運行結果
com.tom.servlets.UserService@48b4721b
$user.name
$user.getName()
tom
tom
$user.save()
2.6 總結
1.可以通過Velocity將Java的對象注入到Context中,這樣在vm中可以獲得這個注入的Java對象,例子中調用了這個Java對象的toString方法
2.在vm中,僅僅能調用Java對象的帶有String類型參數的方法,這是非性常巨大的局限,因為在vm中,沒法像在JSP中通過<%%>創建Java對象,然后把它作為參數調用Java的方法
3.對於setter和getter,可以直接使用屬性進行方法,例如$user.getName和$user.name是等價的,不管User類是否定義了name屬性(比如把User類中的屬性name改名為xname,getName和setName方法名不變)
4.$user.save()不能正確解析,也就是說,vm只能調用Java對象帶String類型參數的方法(POJO的get方法除外)
3 脫離servlet使用velocity
Java代碼
- package com.tom.velocity;
- import java.io.InputStream;
- import java.io.StringWriter;
- import java.util.Properties;
- import org.apache.velocity.Template;
- import org.apache.velocity.VelocityContext;
- import org.apache.velocity.app.VelocityEngine;
- public class HelloVelocity {
- public static void main(String[] args) throws Exception {
- //實例化並初始化Velocity模板引擎
- VelocityEngine ve = new VelocityEngine();
- Properties p = new Properties();
- InputStream in = HelloVelocity.class.getClassLoader().getResourceAsStream("velocity.properties");
- p.load(in);
- ve.init(p);
- //從指定目錄下加載自定的vm文件
- Template t = ve.getTemplate("vm/hello.vm");
- //創建Velocity上下文環境,用於在vm和Java傳值
- VelocityContext context = new VelocityContext();
- context.put("name", "tom");
- context.put("job", "code-farmer");
- //將模板序列化為字符串文檔,進行打印
- StringWriter writer = new StringWriter();
- t.merge(context, writer);
- //將模板引擎解析的結果打印輸出
- System.out.println(writer.toString());
- //輸出
- /*
- <p>name: tom</p>
- <p>job: code-farmer</p>
- */
- }
- }
3.1 velocity.properties文件
存放在classpath根目錄下,內容:
Java代碼
- resource.loader=class
- #Why ClasspathResourceLoader search the vm in the root directory of classpath
- #This means, <class.resource.loader.path> doesn't take effect
- class.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
- class.resource.loader.path=vm
3.2 hello.vm文件
存放在{classpath根目錄}/vm目錄下。
Java代碼
- <p>name: $name</p>
- <p>job: $job</p>
3.3 java中使用詳細實例
3.3.1 模板內容
<?xml version="1.0" encoding="utf-8"?>
<T24 xmlns="http://www.temenos.com/T24/OFSML/130" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.temenos.com/T24/OFSML/130 ofsml13.xsd">
<ofsmlHeader>
<requestId>$_utils.uuid()$ofsRequest.getTxCode()</requestId>
<correlationId/>
</ofsmlHeader>
<serviceRequest>
<securityContext>
<userName>$ofsRequest.getName()</userName>
<password>$ofsRequest.getPassword()</password>
<company>$ofsRequest.getCompany()</company>
</securityContext>
<ofsStandardEnquiry name="$ofsRequest.getEnquiryName()">
#set($struct = $ofsRequest.getStruct)
#foreach ($item in $ofsRequest.getMessageData())
#if($_tools.isEmpty($struct) || $_tools.isNotEmpty($struct.get($item.getName())))
<selectionCriteria operand="$item.getOperator()">
<fieldName>$item.getName()</fieldName>
<value>#foreach($vItem in $item.getValue())$vItem #end</value>
</selectionCriteria>
#end
#end
</ofsStandardEnquiry>
</serviceRequest>
</T24>
3.3.2 重點部分java代碼
// 組合請求消息報文對象
OFSEnquiryRequest ofsRequest = new OFSEnquiryRequest();
ofsRequest.setHeader(msgType + SPLIT_ROW + txCode);
ofsRequest.setName(name);
ofsRequest.setPassword(password);
ofsRequest.setCompany(company);
ofsRequest.setEnquiryName((String) msgHead.get("enquiryName"));
ofsRequest.setStruct(struct);
ofsRequest.setTxCode(txCode);
if (null != msgBody && msgBody.containsKey("messageData")) {
ofsRequest.setMessageData((List<OFSEnquiryReqItem>) msgBody.get("messageData"));
}
// 根據模板組合請求xml內容
VelocityContext ctx = new VelocityContext();
ctx.put("_tools", Tools.getInstance());
ctx.put("_utils", VelocityUtil.getInstance());
ctx.put("ofsRequest", ofsRequest);
String ofsmlEqyXml = "";
try {
// 變量REQ中保存了上面的模板內容
ofsmlEqyXml = VelocityHelper.getText(REQ, ctx);
} catch (Exception e) {
}
4.Velocity模板優缺點
對於大部分的應用來說,使用 FreeMarker 比 Velocity 更簡單,因為 Velocity 還必須編寫一些自定義的toolbox類以及一遍遍重復的編寫一些比較通用的模版代碼,因此也就喪失了剛開始開發時更多的寶貴時間。另外使用工具類和變通的方法在模版引擎中似乎不是一個非常有效的做法。同時,Velocity 的做法使得在Velocity的模版中大量的跟 Java 對象進行交互,這違反了簡單的原則,盡管你也可以將代碼轉入控制器中實現。當然,如果你像使用 Velocity 一樣來使用 FreeMarker ,那么 FreeMarker 也可以跟 Velocity 一樣簡單。
Velocity 一個優於 FreeMarker 的地方在於它有很廣泛的第三方支持以及一個非常龐大的用戶社區,你可以通過這個社區獲得到很多的幫助,相反的 FreeMarker 在這方面要差很多。當然,也有越來越多的第三方軟件開始在支持 FreeMarker 。
velocity性能比freemarker好很多,應該是最好的,又看到說性能超過jsp。