The Velocity Template Language (VTL)目标是提供一个简洁,易学的方法将动态内容展现到web page
上. a web page 设计者可以没有任何编程经验就可以在一天内学会使用它增强你的站点的展示力!.
VTL 使用引用(references )这种方式将dynamic content(动态内容,一般指java 代码生成的数据对象)
加入到你的web site,Velocity 中的变量(variable)只是refernce 中的一种. Variables 是用来描述从
引入到视图模板中的java 数据对象。当然,java 代码也可以从模板的VTL 中获取数据.以下是一个写在
HTML 中的VTL 变量:
#set( $a = "Velocity" )
VTL 声明( statement),所以的VTL statement 都是以#开头,且包含一个指示符(这里是set),当客户
访问你的页面时, the Velocity Templating Engine 将搜索页面中的所有# 符号,如果确定这是一个
VTL 声明时就按一定规则处理动态内容, 符号#仅仅只是表明这可能是一个VTL 声明.
符号# 所跟的set 我们用“指示符”这一名词来称呼它(随后介绍更多的指示符), set 指示符使用一个
表达式(expression) (包含在一对括号里) –将一个值value (这里是Velocity)付给变量a,(变量名
在左边,值在右边,用=组合起来).
在以上的例子中,变量是a ,而符号“$”表明它是一个变量,Velocity 中所有变量以符号”$”开头,所
付的值要用双引号括起, 这个值中还可以再添加Velocity 变量,如"Hello $name",输出的将是name
变量所付的值。
这是理解VTL 基础的规则:
以$开头的表示“引用”意思是取得一些东东.而”指示”(Directives)则以#开头来表示,有点“做些
什么动作”的意思.
如上便, #set 用来指定值给一个变量名$a, 以“$”标示的变量名a 的值就是"Velocity".
Escaping Valid VTL References(封装有效的引用
)
如下示,如果没有#set( $email = "foo" )这一行且java 代码中Context 对象中没有放放email 对象,
将直接输出$email.
#set( $email = "foo" )
$email
如果email 己定义了(比如它的值是foo),而这里你却想输出$email. 这样一个字符串,就需要使用转
义字符”\”.
## The following line defines $email in this template:
#set( $email = "foo" )
$email
\$email
\\$email
\\\$email
上面的模板在web 页面上的输出将是:
foo
$email
\foo
\$email
但如果email 并没有定义,我们这样写:.
领先的java 与.Net 技术推广者
www.NetJava.cn 9
$email
\$email
\\$email
\\\$email
输出就原封不动了:
$email
\$email
\\$email
\\\$email
注意:当己定义变量和未定义变量一起输出时,会输出字面意思,如下便,$moon 是未定义的:
#set( $foo = "gibbous" )
$moon = $foo
输出到web 页面中将是
$moon = gibbou
11.Case Substitution(可选的格式)
至此,你对velocity 的refenerce 己比较熟悉了, 你可以在你的模板中开始应用这些功能. 但你还可以
知道的是Velocity references 从java 语法中汲取了一些优点以便模板设计者更容易使用VTL.比如:
$foo
$foo.getBar()
## 等同于
$foo.Bar
$data.setUser("jon")
##等同于
#set( $data.User = "jon" )
$data.getRequest().getServerName()
##等同于
$data.Request.ServerName
## is the same as
${data.Request.ServerName}
这里示例了你可选的一些引用方式. VTL 汲取了java 语法和java bean 的一些简洁语法以解析java 代码
中Context 中的对象和这些对象的命令及属性---这样,一个java 对象的所有功能都可以展示到视图中
了.
领先的java 与.Net 技术推广者
www.NetJava.cn 10
Velocity 也借见了java Bean 的规范(Bean specifications defined by Sun Microsystems), 是大小写
敏感的; 但Velocity 会尽可能的帮你修正错误. 当命令getFoo() 通过指令$bar.foo 在模板中引用
时,Velocity 的搜索规则我们在前面己讲了,你还记得是什么吗?.
注意:模板中引用的必须是通过java Bean 中的getter/setter 实现的,而直接的java 对象的数据域是
不能直接引用的,如$foo.Name 会解析到class Foo's getName() 的实例方法,但不会解析到Foos 类的
public Name 这个实例变量.
12.Directives(指令符号)
模板设计者使用“引用“生成动态内容, 指令(directives) – 简单的说就是设计者在模板中操作java
对象—让视图设计者全面控制输出内容的格式.
指令总是以#开头后面紧跟具体的指令符. 就像引用一样(指令的一种),可以将指令理解为”表示这里
是一个什么东东).如下例生成一个出错提示:
#if($a==1)true enough#elseno way!#end
这个例子中应使用括号将else 分开.
#if($a==1)true enough#{else}no way!#end
1.#set 指令
#set 用来给一个引用赋值.值可以被赋给变量引用或属性引用, 但要将它们放入括号中,如下示:
#set( $primate = "monkey" )
#set( $customer.Behavior = $primate )
“左操作数被赋值“是引用操作的一个规则.=号右侧可能是以下类型之一:
Variable reference 变量引用
String literal 字符串
Property reference 属性引用
Method reference 命令引用
Number literal 数字
ArrayList 数组
Map 映射
下面是对上述类型设置的示例:
#set( $monkey = $bill ) ## variable reference
#set( $monkey.Friend = "monica" ) ## string literal
#set( $monkey.Blame = $whitehouse.Leak ) ## property reference
#set( $monkey.Plan = $spindoctor.weave($web) ) ## method reference
领先的java 与.Net 技术推广者
www.NetJava.cn 11
#set( $monkey.Number = 123 ) ##number literal
#set( $monkey.Say = ["Not", $my, "fault"] ) ## ArrayList
#set( $monkey.Map = {"banana" : "good", "roast beef" : "bad"}) ## Map
注意: 在ArrayList 类型引用的例子中,其原素定义在数组[..]中, 因此,你可以使表
$monkey.Say.get(0)访问第一个元素.
类似的,引用Map 的例子中, 原素定义在{ } 中,其键和值间以:隔成一对,使用
$monkey.Map.get("bannana") 在上例中将返回'good', ( $monkey.Map.banana 也会有同样效果).
下面是一般的计算表达式:
#set( $value = $foo + 1 )
#set( $value = $bar - 1 )
#set( $value = $foo * $bar )
#set( $value = $foo / $bar )
但注意:如果右边的操作数是一个属性或命令的引用而返回null,那么赋值将不会成功,且在随后的VTL
中也不能再取出使用. 如下例:
#set( $result = $query.criteria("name") )
The result of the first query is $result
#set( $result = $query.criteria("address") )
The result of the second query is $result
如果$query.criteria("name") 返回的是字符串"bill", 但$query.criteria("address") 返回null,
上面的TVL 输出结果将是:
The result of the first query is bill
The result of the second query is bill
这对与初学者的理解有些麻烦,比如在#foreach loops 中, 你使用#set 给一个属性或命令赋值时,如
下例示:
#set( $criteria = ["name", "address"] )
#foreach( $criterion in $criteria )
#set( $result = $query.criteria($criterion) )
#if( $result )
Query was successful
#end
领先的java 与.Net 技术推广者
www.NetJava.cn 12
#end
在上例中,就不能依赖if( $result )来决定查询是否成功. $result 一但被#set 为null (context 会
同样), 它将不能被赋其它值(不能从context 中取出).
一个解决办法是,每次都将$result 设为false. 如果$query.criteria() 调用成功,就可以检测到.
#set( $criteria = ["name", "address"] )
#foreach( $criterion in $criteria )
#set( $result = false )
#set( $result = $query.criteria($criterion) )
#if( $result )
Query was successful
#end
#end
注意: #set 不需要使用#end 来声明结尾.
基本语法
1、"#"用来标识Velocity的脚本语句,包括#set、#if 、#else、#end、#foreach、#end、#iinclude、#parse、#macro等;
如:
#if($info.imgs)
<img src="$info.imgs" border=0>
#else
<img src="noPhoto.jpg">
#end
2、"$"用来标识一个对象(或理解为变量);如
如:$i、$msg、$TagUtil.options(...)等。
3、"{}"用来明确标识Velocity变量;
比如在页面中,页面中有一个$someonename,此时,Velocity将把someonename作为变量名,若我们程序是想在someone这个变量的后面紧接着显示name字符,则上面的标签应该改成${someone}name。
4、"!"用来强制把不存在的变量显示为空白。
如当页面中包含$msg,如果msg对象有值,将显示msg的值,如果不存在msg对象同,则在页面中将显示$msg字符。这是我们不希望的,为了把不存在的变量或变量值为null的对象显示为空白,则只需要在变量名前加一个“!”号即可。
如:$!msg
二,关于#set的使用
在万不得已的时候,不要在页面视图自己声明Velocity脚本变量,也就是尽量少使用#set。有时候我们需要在页面中显示序号,而程序对象中又没有包含这个序号属性同,可以自己定义。如在一个循环体系中,如下所示:
#set ($i=0)
#foreach($info in $list)
序号:$i
#set($i=$i+1)
#end
三,Velocity脚本语法摘要
1、声明:#set ($var=XXX)
左边可以是以下的内容
Variable reference
String literal
Property reference
Method reference
Number literal #set ($i=1)
ArrayList #set ($arr=["yt1","t2"])
算术运算符
2、注释:
单行## XXX
多行#* xxx
xxxx
xxxxxxxxxxxx*#
References 引用的类型
3、变量 Variables
以 "$" 开头,第一个字符必须为字母。character followed by a VTL Identifier. (a .. z or A .. Z).
变量可以包含的字符有以下内容:
alphabetic (a .. z, A .. Z)
numeric (0 .. 9)
hyphen ("-")
underscore ("_")
4、Properties
$Identifier.Identifier
$user.name
hashtable user中的的name值.类似:user.get("name")
5、Methods
object user.getName() = $user.getName()
6、Formal Reference Notation
用{}把变量名跟字符串分开
如
#set ($user="csy"}
${user}name
返回csyname
$username
$!username
$与$!的区别
当找不到username的时候,$username返回字符串"$username",而$!username返回空字符串""
7、双引号 与 引号
#set ($var="helo")
test"$var" 返回testhello
test'$var' 返回test'$var'
可以通过设置 stringliterals.interpolate=false改变默认处理方式
8、条件语句
#if( $foo )
<strong>Velocity!</strong>
#end
#if($foo)
#elseif()
#else
#end
当$foo为null或为Boolean对象的false值执行.
9、逻辑运算符:== && || !
10、循环语句#foreach($var in $arrays ) // 集合包含下面三种Vector, a Hashtable or an Array
#end
#foreach( $product in $allProducts )
<li>$product</li>
#end
#foreach( $key in $allProducts.keySet() )
<li>Key: $key -> Value: $allProducts.get($key)</li>
#end
#foreach( $customer in $customerList )
<tr><td>$velocityCount</td><td>$customer.Name</td></tr>
#end
11、velocityCount变量在配置文件中定义
# Default name of the loop counter
# variable reference.
directive.foreach.counter.name = velocityCount
# Default starting value of the loop
# counter variable reference.
directive.foreach.counter.initial.value = 1
12、包含文件
#include( "one.gif","two.txt","three.htm" )
13、Parse导入脚本
#parse("me.vm" )
14、#stop 停止执行并返回
15、定义宏Velocimacros ,相当于函数 支持包含功能
#macro( d )
<tr><td></td></tr>
#end
调用
#d()
16、带参数的宏
#macro( tablerows $color $somelist )
#foreach( $something in $somelist )
<tr><td bgcolor=$color>$something</td></tr>
#end
#end
17、Range Operator
#foreach( $foo in [1..5] )
这次吃亏的主要是红色部分,很多地方没有加感叹号,
导致画面直接显示了变量名${xxx.yyy}
velocity的#macro功能挺强大.
#macro,类似于宏定义,用于自定义相应的标记。
如下定义了一段宏,用于输出表格中的列表
#macro( tablerows $color $somelist )
#foreach( $something in $somelist )
<tr><td bgcolor=$color>$something</td></tr>
#end
#end
在模版中,只需要使用#tablerows($color $somelist)就可以取代里面的代码了:
#set( $greatlakes = ["Superior","Michigan","Huron","Erie","Ontario"] )
#set( $color = "blue" )
<table>
#tablerows( $color $greatlakes )
</table>