回到顶部
您的当前位置: 编程语言> JAVA> JAVA项目> Velocity
Apache Velocity(五)指令
2014-06-03 17:11:11
标签: 网络整理 Velocity 指令

Reference允许设计者使用动态的内容,而directive使得你可以应用java代码来控制你的显示逻辑,从而达到你所期望的显示效果。

1) set

#set标志是用于对一个reference赋值,值会赋给一个变量或者一个属性,而且赋值会在括号里出现:

#set($primate="monkey")
#set($customer.Behavior=$primate)

左边(LHS) 一定是一个变量或者一个属性,右边(RHS)可以是下面中的一个类型:

    ◇ 变量

    ◇ 字符串

    ◇ 属性

    ◇ 方法

    ◇ 数字

    ◇ 数组

这些例子显示上述的每一种类型:

## variable reference
#set($monkey=$bill)

## string literal
#set($monkey.Friend="monica")

## property reference
#set($monkey.Blame=$whitehouse.Leak)

## method reference
#set($monkey.Plan=$spindoctor.weave($web))

##number literal
#set($monkey.Number=123)

## ArrayList
#set($monkey.Say=["Not",$my,"fault"])

注意:最后一个例子的取值方法为:$monkey.Say.get(0)。

右边(RHS)也可以是一个简单的算术表达式:

#set( $value = $foo + 1 )
##减号必须有空格
#set( $value = $bar ­- 1 )
#set( $value = $foo * $bar )
#set( $value = $foo / $bar )

如果你的RHS是一个null,VTL的处理将比较特殊:它将指向一个已经存在的 reference,这对初学者来讲可能是比较费解的。例如:

#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,则显示的结果如下:

The result of the first query is bill
The result of the second query isbill

这容易使新手糊涂:创建一个#foreach循环,企图想通过一个属性或者一个方法 #set一个reference,然后马上就用#if测试。例如:

#set( $criteria = ["name","address"] )
#foreach( $criterion in $criteria )
  #set( $result = $query.criteria($criterion))
  #if( $result )
    Query was successful
  #end
#end

在上面的例子中,程序将不能智能的根据$result的值决定查询是否成功。在$result被#set后(added tothe context),它不能被设置回null(removedfrom the context)。打印的结果将显示两次查询结果都成功了,但是实际上有一个查询是失败的。

为了解决以上问题我们可以通过预先定义的方式:

#set( $criteria = ["name","address"] )
#foreach( $criterion in $criteria )
  #set( $result = false )
  #set( $result = $query.criteria($criterion))
  #if( $result )
    Query was successful
  #end
#end

不像其他Velocity指示符号,#set没有一个#end结束。

2) stringliteral

当你使用#setdirective,Stringliteral封闭在一对双引号内。象下面:

#set( $directoryRoot = "www" )
#set( $templateName = "index.vm")
#set( $template ="$directoryRoot/$templateName" )
$template

上面这段代码的输出结果为:

www/index.vm

但是,当stringliteral被封装在单引号内时,它将不被解析:

#set( $foo = "bar" )
$foo

#set( $blargh = '$foo' )
$blargh

输出为:

bar $foo

上面这个特性可以通过修改velocity.properties文件的stringliterals.interpolate = false的值来改变上面的特性是否有效。

3) if elseif ... else

当一个web页面被生成时使用Velocity的#if directrive,如果条件成立的话可以在页面内嵌入文字。例如:

#if( $foo )
  <strong>Velocity!</strong>
#end

上例中的条件语句将在以下两种条件下成立:

(a) $foo是一个boolean型的变量,且它的值为true

(b) $foo变量的值是不为null的string或者不为空的collection。

(c) $foo变量的值是不为null的对象(除了string和collection)

这里需要注意一点:Velocity context仅仅能够包含对象,所以当我们说“boolean”时实际上代表的时一个Boolean对象。即便某个方法返回的是一个boolean值,Velocity也会利用内省机制将它转换为一个Boolean的相同值。如果条件成立,那么#if#end之间的内容将被显示。在这个例子中,如果$foo的值为true,输出为“Velocity!”。相反地,如果$foo是一个null值,或者是一个false值,表达式值为false,没有输出。

#elseif和#else元素可以同#if一同使用。注意:Velocity模板引擎遇到一个为 true 值的表达式就会停止。在下面的例子,假设$foo=15,$bar=6:

#if( $foo < 10 )
  <strong>Go North</strong>
#elseif( $foo == 10 )
  <strong>Go East</strong>
#elseif( $bar == 6 )
  <strong>Go South</strong>
#else
  <strong>Go West</strong>
#end

在这个例子中,$foo10大,所以在开始的两个比较中都失败。接着$bar6比较为true的所以输出为GO South

注意这里的Velocity的数字是作为Integer来比较的――其他类型的对象将使得条件为false,但是与java不同它使用“==”来比较两个值,而且velocity要求等号两边的值类型相同。

4) 关系逻辑运算符

Velocity中使用等号操作符判断两个变量的关系。这里有个简单例子关于等于号的使用:

#set ($foo = "deoxyribonucleicacid")
#set ($bar = "ribonucleic acid")
#if ($foo == $bar)
In this case it's clear they aren'tequivalent. So...
#else
They are not equivalent and this will bethe output.
#end

Velocity有AND、OR和NOT逻辑运算符。

## logical AND

#if( $foo && $bar )
<strong> This AND that</strong>
#end

只有当$foo和$bar都为true,#if才会得到true值。如果$foo=false,表达式的值为false,$bar就不会求值。如果$foo的值为true,Velocity模板引擎会检查$bar的值,如果$bar=true,整个表达式的值为true,输出为“This AND that”。如果$bar=false,整个表达式的值为false,没有输出。

逻辑OR的工作方式一样,除了只要有一个值为true,整个表达式的值就为true。考虑一下下面的例子:

## logical OR

#if( $foo || $bar )
<strong>This OR That</strong>
#end

如果$foo=true,Velocity模板引擎就没有必要查找$bar,无论$bar是true还是false,表达式的值为true,输出为“This OR That”。如果$foo=flase,$bar的值就一定要检查,在这个例子中,如果$bar同样是false,表达式的值为false,没有输出。从另外一个角度看,如果$bar的值为true,整个表达式的值为true,输出为 “This OR That”。

关于逻辑 NOT,只有一个疑问:

##logical NOT

#if( !$foo )
<strong>NOT that</strong>
#end

如果$foo=true,!$foo的值为false,没有输出。如果$foo=false,!$foo的值为true,输出为“NOT that”。注意不要跟quiet reference $!foo混为一谈,那是完全不一样的。

5) foreach循环

#foreach用于循环,例子:

<ul>
#foreach( $product in $allProducts )
  <li>$product</li>
#end
</ul>

每次循环$allProducts中的一个值都会赋给$product变量。$allProducts可以是一个Vector、Hashtable或者Array。分配给$product的值是一个java对象,并且可以通过变量被引用。例如:如果$product是一个java的Product类,并且这个产品的名字可以通过调用他的getName()方法得到。

现在我们假设$allProducts是一个Hashtable,如果你希望得到它的key应该像下面这样:

<ul>
#foreach( $key in $allProducts.keySet() )
  <li>Key: $key &shy;> Value: $allProducts.get($key)</li>
#end
</ul>

Velocity还特别提供了得到循环次数的方法,以便你可以像下面这样作:

<table>
#foreach( $customer in $customerList)
  <tr><td>$velocityCount</td><td>$customer.Name</td></tr>
#end
</table>

$velocityCount变量的名字是Velocity默认的名字,你也可以通过修改velocity.properties文件来改变它。默认情况下,计数从“1”开始,但是你可以在velocity.properties设置它是从“1”还是从“0”开始。

下面就是文件中的配置:

# 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
6) include

#include script element允许模板设计者引入本地文件,被引入文件的内容将不会通过模板引擎被render。为了安全的原因,被引入的本地文件只能在TEMPLATE_ROOT目录下。

#include( "one.txt" )

#include引用的文件用引号括起来,如果您需要引入多个文件,可以用逗号分隔就行:

#include( "one.gif","two.txt","three.htm")

在括号内可以是文件名,但是更多的时候是使用变量的,这用于根据页面提交的需求而输出,这里有一个例子同时有文件名和变量:

#include( "greetings.txt",$seasonalstock )
7) 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是可以递归调用的,例如:如果dofoo.vm包含如下行:

Count down.
#set( $count = 8 )
#parse( "parsefoo.vm" )
All done with dofoo.vm!

那么在parsefoo.vm模板中,你可以包含如下VTL:

$count
#set( $count = $count &shy; 1 )
#if( $count > 0 )
  #parse( "parsefoo.vm" )
#else
  All done with parsefoo.vm!
#end

在显示“Countdown”后,Velocity通过parsefoo.vm,从8往下数。当计数到了0,它就会显示“All done with parsefoo.vm!”。在这时,Velocity会返回到dofoo.vm,输出信息:“Alldone with dofoo.vm!”。

8) break 、 stop

#break跳出循环,循环以外代码继续执行。

#stop直接终止输出,循环以外代码终止执行,页面所有均不进行渲染。

#foreach($i in [1..10])
  #if($i==1)
  #break  ##stop
  #end
  $i
#end
1

(a) 注释掉break和stop时,输出:123456789101

(b) 仅有break命令时,输出:1

(c) 仅有stop命令时,输出为空,stop后面页面所有内容均不进行渲染

停止执行模板引擎并返回,把它应用于debug是很有帮助的。

9) evaluate

动态执行一串字符串的值:

#evaluate('string with VTL #if(true)will bedisplayed#end')

渲染结果:string with VTL willbe displayed

#set($source1 = "abc")
#set($select = "1")
#set($dynamicsource = "$source$select")
## $dynamicsource is now the string '$source1' 
#evaluate($dynamicsource)

渲染结果:abc

10) define

类似于C语言的#define命令。

#define($hello)
Hello ${who}!
#end
#set($who = "World")
$hello

渲染结果:Hello World!