简介
Apache Velocity 是一个基于java的模板引擎(template engine)。它允许任何人仅仅简单的使用模板语言(template language)来引用由java代码定义的对象。
应用场景
- Web 应用:开发者在不使用 JSP 的情况下,可以用 Velocity 让 HTML 具有动态内容的特性
- 源代码生成:Velocity 可以被用来生成 Java 代码、SQL 或者 PostScript
- 自动 Email:很多软件的用户注册、密码提醒或者报表都是使用 Velocity 来自动生成的
- 转换 xml
语法概要
在 Velocity 中所有的关键字都是以#开头的,而所有的变量则是以$开头。下面为具体语法规则。
注释
单行注释
## 这是单行注释
多行注释
#*
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 1.1
@author xiao
*#
变量
在Velocity中也有变量的概念,使用 符 声 明 变 量 , 可 以 声 明 变 量 也 可 以 对 变 量 进 行 赋 值 ( 变 量 是 弱 类 型 的 ) 。 另 外 还 可 以 使 用 符声明变量,可以声明变量也可以对变量进行赋值(变量是弱类型的)。另外还可以使用 符声明变量,可以声明变量也可以对变量进行赋值(变量是弱类型的)。另外还可以使用取出在VelocityContext容器中存放的值
#set(${!name} = "velocity") ## string
#set(${!foo} = $bar) ## variable reference
#set($foo =“hello”) ## string
#set($foo.name = $bar.name) ## property reference
#set($foo.name = $bar.getName($arg)) ## method reference
#set($foo = 123) ## number
#set($foo = [“foo”,$bar]) ## ArrayList
注意变量定义语句为#set( $),获取时需要加
模板文件可以使用name或name或{name}定义变量,建议使用后者,name和name和names 的两个变量,如果不选用大括号的话,引擎就没有办法正确识别$names 这个变量。
需要注意,上面代码中 ! 的 写 法 , 使 用 !{}的写法,使用 !的写法,使用vari获取变量时,如果变量不存在,Velocity引擎会将其原样输出,通过使用 ! 的 形 式 可 以 将 不 存 在 的 变 量 变 成 空 白 输 出 . 推 荐 使 用 !{}的形式可以将不存在的变量变成空白输出.推荐使用 !的形式可以将不存在的变量变成空白输出.推荐使用!{}写法
循环
在Velocity中可以使用循环语法遍历集合,语法结构如下:
#foreach($item in $list)
$item
$velocityCount
#end
其中,$item代表遍历的每一项,velocityCount是Velocity提供的用来记录当前循环次数的计数器,默认从1开始计数,可以在velocity.properties文件中修改其初始值
语句的嵌套
#foreach ($element in $list)
## inner foreach 内循环
#foreach ($element in $list)
This is $element. $velocityCount <br>inner<br>
#end
## inner foreach 内循环结束
## outer foreach
This is $element.
$velocityCount <br>outer<br>
#end
语句中也可以嵌套其他的语句,如#if…#else…#end等。
条件控制语法
在Velocity中可以使用条件语法对流程进行控制
#if(condition)
...dosonmething...
#elseif(condition)
...dosomething...
#else
...dosomething...
#end
例如
#if($iAmVariable == "goo00d!")
#set($iAmVariable = "goodddd!")
$!iAmVariable
#else
#set($iAmVariable = "goonnnnnn")
$!iAmVariable
#end
宏
在Velocity中也有宏的概念,可以将其作为函数来理解,使用#macro
声明宏
①宏的定义
#macro(宏的名称 $参数1 $参数2 …)
语句体(即函数体)
#end
②宏的调用
#宏的名称($参数1 $参数2 …)
说明:参数之间用空格隔开。
举例
## 声明宏
#macro(sayHello $name)
hello $name
#end
## 使用宏
#sayHello("NICK")
关系和逻操作符
Velocity 也具有逻辑AND, OR 和 NOT 操作符。
## example for AND
#if($foo && $bar)<strong>This and that</strong>
#end
例子中#if() 指令仅在 f o o 和 foo 和 foo和bar 都为真的时候才为真。如果$foo 为假,则表达式也为假;并且 $bar 将不被求值。如果 f o o 为 真 , V e l o c i t y 模 板 引 擎 将 继 续 检 查 foo 为真,Velocity 模板引擎将继续检查 foo为真,Velocity模板引擎将继续检查bar的值,如果 $bar 为真,则整个表达式为真。并且输出This AND that 。如果 $bar 为假,将没有输出因为整个表达式为假。
#stop
停止执行模板引擎并返回,把它应用于debug是很有帮助的。
#include与#parse
#include和#parse的作用都是引入本地文件, 为了安全的原因,被引入的本地文件只能在
TEMPLATE_ROOT目录下。
区别:
-
与#include不同的是,#parse只能指定单个对象。而#include可以有多个
如果您需要引入多个文件,可以用逗号分隔就行:
#include (“one.gif”, “two.txt”, “three.htm” )
在括号内可以是文件名,但是更多的时候是使用变量的:
#include ( “greetings.txt”, $seasonalstock )
-
#include被引入文件的内容将不会通过模板引擎解析;
而#parse引入的文件内容Velocity将解析其中的velocity语法并移交给模板,意思就是说
相当与把引入的文件copy到文件中。
#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!
注意:在vm中使用#parse来嵌套另外一个vm时的变量共享问题。如:
->a.vm 里嵌套 b.vm;
->a.vm 里定义了变量 $param;
->b.vm 里可以直接使用$param,无任何限制。
但需要特别注意的是,如果b.vm里同时定义有变量$param,则b.vm里将使用b.vm里定义的值。
转义字符’'的使用
如果reference被定义,两个’\’意味着输出一个’\’,如果未被定义,刚按原样输出。
如:
#set($email = “foo” )
$emai
l\$email
输出:
foo
\foo
如果$email 未定义
输出:
内置对象
Velocity内置了一些对象,在vm模版里可以直接调用,列举如下:
r e q u e s t 、 request、 request、response、$session,另外,模板内还可以使用 $msg内的消息工
具访问 Struts 的国际化资源,达到简便实现国际化的方法。
数组访问
对数组的访问在Velocity中存在问题,因为Velocity只能访问对象的方法,而数组
又是一个特殊的Array,所以虽然数组可以进行循环列举,但却不能定位访问特定
位置的元素,如 strs[2],数组对固定位置元素的访问调用了Array的反射方法
get(Object array, int index),而Velocity没能提供这样的访问,所以数组要么改成
List等其他类容器的方式来包装,要么就通过公用Util类的方式来提供,传入数组
对象和要访问的位置参数,从而达到返回所需值的目的。