原文:http://blog.csdn.net/qq_25237663/article/details/52262532javascript
Velocity是一個基於Java的模板引擎,經過特定的語法,Velocity能夠獲取在java語言中定義的對象,從而實現界面和java代碼的真正分離,這意味着可使用velocity替代jsp的開發模式了(實際上筆者所在的公司已經這麼作了)。這使得前端開發人員能夠和 Java 程序開發人員同步開發一個遵循 MVC 架構的 web 站點,在實際應用中,velocity還能夠應用於不少其餘的場景.css
1. Velocity的介紹
Velocity是一個基於Java的模板引擎,其提供了一個Context容器,在java代碼裏面咱們能夠往容器中存值,而後在vm文件中使用特定的語法獲取,這是velocity基本的用法,其與jsp、freemarker並稱爲三大視圖展示技術,相對於jsp而言,velocity對先後端的分離更加完全:在vm文件中不容許出現java代碼,而jsp文件中卻能夠.html
做爲一個模塊引擎,除了做爲先後端分離的MVC展示層,Velocity還有一些其餘用途,好比源代碼生成、自動email和轉換xml等,具體的用法能夠參考這篇文章.前端
2. Velocty的基本用法
在這裏咱們以一個HelloVelocity做爲Velocity的入門實例.首先在官網下載velocity的最新發布包,新建普通java項目,引入其中的velocity-1.7.jar和lib文件夾下的全部jar包便可. 而後分爲以下兩步:java
2.1 初始化Velocity引擎
編寫HelloVelocity.java文件以下:jquery
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
public static void main(String[] args) {
VelocityEngine ve =
new VelocityEngine();
ve.setProperty(RuntimeConstants.RESOURCE_LOADER,
"classpath");
ve.setProperty(
"classpath.resource.loader.class", ClasspathResourceLoader.
class.getName());
ve.init();
Template t = ve.getTemplate(
"hellovelocity.vm");
VelocityContext ctx =
new VelocityContext();
ctx.put(
"name",
"Velocity");
List
list =
new ArrayList();
list.add(
"1");
list.add(
"2");
ctx.put(
"list",
list);
StringWriter sw =
new StringWriter();
t.merge(ctx,sw);
System.out.println(sw.toString());
}
首先,咱們在代碼中初始化了VelocityEngine這個模板引擎,對其設置參數進行初始化,指定使用ClasspathResourceLoader來加載vm文件。而後咱們就能夠往VelocityContext這個Velocity容器中存放對象了,在vm文件中咱們能夠取出這些變量,從而進行模板輸出.web
2.2 編寫hellovelocity.vm文件
其中,vm文件放在classpath目錄下便可,類加載器會進行加載
hellovelocity.vm文件以下:apache
#set(
$greet = 'hello')
$greet $name#foreach(
$i in $list)
$i#end
控制檯輸出以下:後端
hello Velocity
1
2
2.3 Velocity的基本語法
本文中只簡單的介紹幾個Velocity的基本語法,具體能夠參考這篇文章瀏覽器
3.1 變量
在Velocity中也有變量的概念,使用$符聲明變量,能夠聲明變量也能夠對變量進行賦值(變量是弱類型的)。另外還可使用$取出在VelocityContext容器中存放的值
#set(
${!name} = )
#set(
${!foo} =
$bar)
#set(
$foo =「hello」)
#set(
$foo.name =
$bar.name)
#set(
$foo.name =
$bar.getName(
$arg))
#set(
$foo =
123)
#set(
$foo = [「foo」,
$bar])
須要注意,上面代碼中 $!{}的寫法,使用$vari獲取變量時,若是變量不存在,Velocity引擎會將其原樣輸出,經過使用\$!{}的形式能夠將不存在的變量變成空白輸出.
3.2 循環
在Velocity中可使用循環語法遍歷集合,語法結構以下:
#foreach(
$item in $list)
$item$velocityCount#end
其中,$item表明遍歷的每一項,velocityCount是Velocity提供的用來記錄當前循環次數的計數器,默認從1開始計數,能夠在velocity.properties文件中修改其初始值
3.3 條件控制語法
在Velocity中可使用條件語法對流程進行控制
#if(condition)
...dosonmething
...#elseif(condition)
...dosomething
...#else...dosomething
...#end
3.4 宏
在Velocity中也有宏的概念,能夠將其做爲函數來理解,使用#macro
聲明宏
## 聲明宏#macro(sayHello $name)
hello $name
#end## 使用宏#sayHello("NICK")
3.5 parse和include指令
在Velocity中能夠經過parse或者include指令引入外部vm文件,可是兩者存在區別:include指令會將外部文件原樣輸出,而parse指令會先對其進行解析再輸出(即對外部文件中的vm語法解析)
#parse(
"header.vm")
#include(
"footer.vm")
4. 在web項目中使用Velocity
velocity只是一個模板引擎,在web項目中使用Velocity還得添加一個HTTP框架來處理請求和轉發,apache提供了velocity-tools,其提供了VelocityViewServlet,也可繼承VelocityViewServlet,從而實現本身的HTTP框架
通常都是繼承VelocityViewServlet,重寫handleRequest方法,在其中存入公共的參數.
經過繼承或直接使用VelocityViewServlet,能夠在管理的vm文件中得到request、session與application對象,也能夠直接獲取在這幾個域對象中保存的值,獲取的順序與EL表達式獲取的順序相似:
${request}
–> ${session}
–> ${application}
好比${testArr}
,獲取testArr屬性,velocity會在velocity的context中尋找。沒找到在request域中找,沒找到在session中找.
下面將經過實例的方式講解如何在web項目中使用Velocity
首先引入velocity-tools及其依賴的相關jar包,而後分爲以下4步:
4.1 繼承VelocityViewServlet
經過繼承VelocityViewServlet重寫handleRequest方法,能夠自定義轉發規則
public class MyVelocityViewServlet extends VelocityViewServlet {@Overrideprotected Template
handleRequest(HttpServletRequest request, HttpServletResponse response, Context ctx) {
ctx.put(
"fullName",
"lixiaolin");
request.setAttribute(
"anotherName",
"xlli");
return getTemplate(
"test.vm");
}
}
4.2 配置web.xml
對自定義的VelocityViewServlet配置就像配置普通的Servlet同樣,以下:
<servlet><servlet-name>MyVelocityServlet
</servlet-name><servlet-class>com.lxl.velocity.MyVelocityViewServlet
</servlet-class></servlet><servlet-mapping><servlet-name>MyVelocityServlet
</servlet-name><url-pattern>/servlet/myVelocityServlet
</url-pattern></servlet-mapping>
4.3 編寫vm文件
vm文件是做爲jsp的替代來展現給用戶,在vm文件中能夠得到在Context域或request等域中存放的值。默認狀況下,會在資源根路徑下搜索vm文件,因此直接將vm放在根路徑下便可(也能夠經過配置velocity.properties指定加載路徑)
以下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
#set($greet = "hello")
<!doctype html><html lang="en"><head><meta charset="UTF-8"><title>Document
</title></head><body><p>$!{greet} $!{fullName}
</p><p>my another name is $!{anotherName}
</p></body></html>
4.4 配置velocity.properties
經過配置velocity.properties文件,能夠自定義vm文件加載方式,指定編碼等。固然,也能夠不配置velocity.properties,使用缺省的值便可.
## 設置模板文件加載器,webapp從應用根目錄加載
resource
.loader = webapp
webapp
.resource.loader.class = org
.apache.velocity.tools.view.WebappResourceLoader## 模板路徑,根目錄下的vm文件夾
webapp
.resource.loader.path = /vm
## 設置編碼
input
.encoding = UTF-
8
output
.encoding = UTF-
8
最後,在瀏覽器中訪問http://localhost:8080/VelocityApp/servlet/myVelocityServlet
便可
5. 使用VelocityLayoutServlet
在web站點開發的過程當中,常常會碰到幾個頁面的佈局大體相同,好比引用相同的頭部和尾部、左側邊欄相同等,在使用jsp開發時咱們能夠將頭部等公共文件抽離出來,而後在實際頁面中引入。Velocity也提供了相似的功能,而且該功能更增強大.
apache提供了VelocityLayoutServlet來實現頁面佈局,它是VelocityViewServlet的子類,經過使用VelocityLayoutServlet能夠簡化velocity下頁面佈局開發,可使當forward到一個vm頁面時,把該頁面做爲一個已有頁面佈局的一部分總體顯示出來,好比訪問資料頁面,可以自動把頭、尾部顯示出來
velocity-tools包中已經包含了這個類,其使用分爲以下幾步:
5.1 配置velocity.properties
在/WEB-INF/路徑下配置velocity.properties文件,指定模板佈局文件的位置
input
.encoding=UTF-
8
output
.encoding=UTF-
8## 定義加載器
resource
.loader=webapp
webapp
.resource.loader.cache=false
## 佈局文件夾位置
tools
.view.servlet.layout.directory = /templates/layout
## 定義默認佈局文件
tools
.view.servlet.layout.default.template = layout
.vm## 錯誤模板文件
tools
.view.servlet.error.template = err
.vm
5.2 佈局母版vm文件
佈局layout.vm文件是全部要展現的vm文件的母版,以下所示:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
<!doctype html><html lang="en"><head><meta charset="UTF-8"><title>${page_title}
</title>
#if($!{CSS})
#foreach($_css in ${CSS})
<link type="text/css" rel="stylesheet" href="${ContextPath}/$_css">
#end
#end
</head><body><div class="header">
#parse("/templates/layout/header.vm")
</div><div class="container"><div class="sub">
#parse($sub)
</div><div class="main">
$screen_content
</div></div>
#if($!JS)
#foreach($_js in $JS)
<script type="text/javascript" src="${CntextPath}/${_js}"> #end #end </body> </html>
其中,有個特殊的變量 screen_content,這是Velocity內置的變量,表明將要轉發的頁面
5.3 編寫轉發的vm文件
#set(
$layout = )
#set(
$CSS = [])
#set(
$JS = [])
#set(
$page_title = )
#set(
$sub = )
<div id=>
this is main-show
</div>
5.4 繼承VelocityLayoutServlet
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
public class MyLayoutServlet extends VelocityLayoutServlet {@Overrideprotected void doRequest(HttpServletRequest request, HttpServletResponse response)
throws IOException {
request.setAttribute(
"Request", request);
request.setAttribute(
"ContextPath", request.getContextPath());
request.setAttribute(
"BasePath", request.getScheme() +
"://" + request.getServerName() +
":" + request.getServerPort() + request.getContextPath());
long runtime = System.currentTimeMillis();
super.doRequest(request, response);
if (request.getAttribute(
"close_comment") ==
null) {
Date cur_time = Calendar.getInstance(request.getLocale()).getTime();
PrintWriter pw = response.getWriter();
pw.print(
"\r\n<!-- Generated by VelocityApp Server(");
pw.print(cur_time);
pw.print(
") Cost ");
pw.print(cur_time.getTime() - runtime);
pw.print(
" ms -->");
pw.flush();
pw.close();
}
}
}
6. 附錄及參考文獻
參考文獻
* 使用 Velocity 模板引擎快速生成代碼
* Velocity教程