Velocity的能力远不止web站点开发这个领域,例如,它可以从模板(Template)产生SQL和PostScript、XML,
它也可以被当作一个独立工具来产生源代码和报告,或者作为其他系统的集成组件使用。Velocity也可以为Turbine
Web开发架构提供模板服务( Template Service )。Velocity+Turbine提供一个模板服务的方式允许一个web应用以一个
真正的MVC模型进行开发。
VTL使用 References 来在Web Site内嵌套动态内容,一个变量就是References的一种类型。
VTL使用 Directives 来控制要显示的Java代码逻辑。
下面是一个VTL Statement的例子,它可以被嵌套到HTML代码中:
#set ( $a = “Velocity” );
和所有的VTL Statement一样,这个Statement以#字符开始,当一个在线用户请求页面时,Velocity
Templating Engine将查询当前整个页面以便发现所有#字符,然后确定哪些是VTL Statement,哪些不需要VTL
作任何事情。
和其他References一样以$字符开始,而值总是以双引号封闭。Velocity中仅有String可以被赋值给变量。
记住以下的规则:
使用$字符开始的References用于得到什么;使用#字符开始的Directives用于做些什么。
一旦某个变量被分配了一个值,那么你就可以在HTML文件的任何地方引用它。
为使包含VTL Directives的Statement更具可读性,尽量在新行开始每个VTL Statement,尽管不是必须这么作。
单行注释:
## This is a single line comment.
多行注释:
#*
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 5
@author
*#
在VTL中有三种类型的References:变量(Variables)、属性(Properties)、方法(Methods)。
前面提到Velocity中仅有String可以被赋值给变量,如果有一个对象$foo是一个Integer对象,那么Velocity将调
用它的toString()方法将这个对象转型为String类型,然后将其进行赋值。
(一)变量 格式同Java
(二)属性
例如 $customer.Address:
(1)查找Map对象customer中以address为Key的值;
(2)也可以表示调用customer对象的getAddress()方法。
当页面被请求时,Velocity将确定以上两种方式选用哪种,然后返回适当的值。
(三)方法 是一个由$开始并跟随VTL标识符组成的References,一般还包括一个VTL方法体,如:
$person.setAttributes( [“Strange”, “Weird”, “Excited”] )
VTL属性可以作为VTL方法的缩写:
$customer.getAddress()与$customer.Address效果相同,不同点在于能否指定一个参数列表。
$data.getUser(“jon”)
## is the same as
$data.User(“jon”)
$data.getRequest().getServerName()
## is the same as
$data.Request.ServerName
## is the same as
${data.Request.ServerName}
注意:VTL中不会将Reference解释为对象实例变量。例如:$foo.Name将被解释为Foo对象的getName()
方法,而不是Foo对象的Name实例变量。
References的正式格式 表达如下:
${ mudSlinger } 变量
${ customer.Address } 属性
${ purchase.getTotal() } 方法
VTL支持静态引用符$!,以避免呈现不存在的或者空的引用。
例如:
当页面表单被初始加载时,变量$email还没有值,这时需要能够显示一个空白文本来代替输出"$email"字符
串。此时使用静态引用符$!比较合适:
##正式格式:
这样文本框的初始值就不会是email而是空值。
货币字符$:
在VTL中使用$2.5这样的货币标识能被正常识别,因为VTL中的Reference以一个大写或者小写的字母开始。
转义(逃逸)字符"\":
例如:#set( $email = “foo” )
$email ——> foo
\$email ——> $email
\\$email ——> \foo
\\\$email ——> \\$email
注意:VTL中未被定义的变量将被认为是一个字符串(即转义前后都相同)。
前面提到,使用$字符开始的References用于得到什么;使用#字符开始的Directives用于做些什么。
例如#字符后紧跟一个Directive:set 时,表达式使用括号封闭,其中将一个值赋值给变量。变量被列在左
边(LHS),而值被列在右边(RHS)。
LHS 必须是一个变量或者属性Reference。
RHS 可以是 References(变量、属性、方法)、String、Number、ArrayList、加减乘除算术表达式。
##ArrayList
#set ($monkey.Say = [“Not”, $my, “fault”])
##取值方法:
$monkey.Say.get(0)
注意:
(1)RHS是一个 null 时,VTL的处理将比较特殊:它将指向一个已经存在的 Reference。
#set ( $resut = $query.criteria(“name”))
The result of the first query is $result
#set ( $resut = $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 is bill
由此延伸出的情况:
#set( $criteria = ["name", "address"])
#foreach( $criterion in $criteria )
#set( $result = $query.criteria($criterion))
#if($result)
Query was successful
#end
#end
## 在循环时第二次循环结果为false时,
## 此时程序将不能智能的根据 $result 值决定查询是否成功。在 $result 被#set后
##(added to the context),它不能被设置回null(removed from 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
(2)单引号与双引号
变量或字符串封闭在双引号内能被正常解析,封闭在单引号内时将不被正常解析:
#set ($foo = “bar”)
$foo # bar
#set ($blar = ‘$foo’)
$blar # $foo
本特性可以通过修改velocity.properties文件来改变上面的特性是否有效:
设置 stringliterals.interpolate = false 即可。
#if/#elseif/#else条件语句`
#if ($foo)
Velocity!
#end
在以下两种条件下成立:
(1) $foo 是一个boolean型的变量,且它的值为true
(2) $foo变量的值不为null
#if( $foo < 10 )
Go North
#elseif( $foo == 10 )
Go East
#elseif( $foo == 6 )
Go South
#else
Go West
#end
由于 Velocity Context仅仅能够包含对象,所以此处的数字或boolean等基本类型数据皆通过内省机制转成对应的包装类对象,
此外与Java不同的是,用“==”来比较两个是否相等,并且要求等号两边的值类型相同。
AND、OR和NOT逻辑运算符
AND ——> &&
OR ——> ||
NOT ——> !
Foreach循环
#foreach ($product in $allProducts)
- $product
#end
## 每次循环$allProducts中的一个值都会赋给$product变量。$allProducts可以是一个Vector、Hashtable或者Array。
## 分配给$product的值是一个Java对象,并且可以通过变量被引用。例如:如果$product是一个Java的Product类,
## 并且这个Product的名字可以通过调用他的getName()方法得到。
如果$allProducts是一个Hashtable:
#foreach ($key in $allProducts.keySet())
- Key: $key -> Value: $allProducts.get($key)
- $velocityCount
#end
其中$velocityCount代表循环次数,是Velocity默认的名字,可以通过修改velocity.properties文件来设置;
默认情况下,计数从“1”开始,可以在velocity.properties设置从“1”还是从“0”开始:
directive.foreach.counter.name = velocityCount
directive.foreach.counter.initial.value = 1
#include
1. 引入本地文件(不包含VTL);
2. 文件内容不经过template engine处理;
3. 出于安全性的考虑,引入的文件只能位于TEMPLATE_ROOT目录下;
4. 引入多个文件,可以用逗号分隔,括号内可以是文件名,但是更多的时候是使用变量。
#parse
1. 引入本地文件(包含VTL);
2. 引入的文件只能位于TEMPLATE_ROOT目录下 ;
3. 文件内容经过template engine处理;
4. 括号内只能引入单个文件;
5. 可以通过修改velocity.properties文件parse_direcive.maxdepth的值来控制一个模板包含的最多#parse的个
数( 默认值是10 )。
6. 支持递归调用,将引入的本地文件解析并执行。
#stop
停止执行模板引擎并返回,应用于Debug。
#macro
定义一段可重用的VTL。
#macro ( d )
#end
上述Velocimacro被定义为d,可以用如下方式调用它: #d()
被调用时,Velocity将用 替换为#d()。
每个Velocimacro可以拥有任意数量的参数――甚至0个参数,虽然定义时参数可以随意设置,
但是调用这个Velocimacro时必须指定正确的参数:
#macro ( tablerows $color $somelist )
#foreach ( $something in $somelist )
$something
#end
#end
#set ($greatlakes = [ “Superior”, “Michigan”, “Huron”, “Erie”, “Ontario” ])
#set ( $color = “blue” )
#tablerows( $color $greatlakes )
结果显示如下:
Superior
Michigan
Huron
Erie
Ontario
Velocimacros可以在Velocity模板内实现行内定义(inline),也就意味着和同一个Web Site内的其他Velocity
模板不可以共享此定义。
而定义一个被所有模板共享的Velocimacro,则可以定义在一个Velocimacros模板库(模板库在
velocity.properties中定义):
velocimacro.library=VM_global_library.vm
( 默认情况下velocity查找唯一的一个库,可以通过配置这个属性来指定自己的模板库,多个模板库用逗号隔开)
Velocimacro 参数
可以是 References(变量、属性、方法)、String、Number、ArrayList、boolean值。
注意:当References作为参数传递给Velocimacro时,是以名字的形式传递的。也意味着参数的值在每次
Velocimacro内执行时才会被产生。所以可以将一个方法调用作为参数 (实际传入的是方法名) 传递给Velocimacro,
而每次Velocimacro执行时该方法都会调用并产生不同的值,例如:
#macro (callme $a)
$a $a $a
#end
#callme($foo.bar())
执行的结果是:Reference $foo的bar()方法被执行三次。
如果不需要该特性可以通过以下方法:
#set ($myval = $foo.bar())
#callme ($myval)
velocity.properties中 常用属性配置:
#模板编码:
input.encoding=ISO-8859-1 //模板输入编码
output.encoding=ISO-8859-1 //模板输出编码
#foreach配置
directive.foreach.counter.name = velocityCount //计数器名称
directive.foreach.counter.initial.value = 1 //计数器初始值
directive.foreach.maxloops = -1 //最大循环次数,-1为默认不限制directive.foreach.iterator.name = velocityHasNex //迭代器名称
#set配置
directive.set.null.allowed = false //是否可设置空值
#include配置
directive.include.output.errormsg.start = //错误信息提示结束字符串
#parse配置
directive.parse.max.depth = 10 //解析深度
模板加载器配置
resource.loader = file //模板加载器类型,默认为文件,可定义多个
file.resource.loader.description = Velocity File Resource Loader //加载器描述
file.resource.loader.class = Velocity.Runtime.Resource.Loader.FileResourceLoader //加载器类名称
file.resource.loader.path = . //模板路径
file.resource.loader.cache = false //是否启用模板缓存
file.resource.loader.modificationCheckInterval = 2 //检查模板更改时间间隔
宏配置
velocimacro.permissions.allow.inline = true //是否可以行内定义
velocimacro.permissions.allow.inline.to.replace.global = false //是否可以用行内定义代替全局定义
velocimacro.permissions.allow.inline.local.scope = false //行内定义是否只用于局部
velocimacro.context.localscope = false //宏上下文是否只用于局部 任何在Velocimacro内通过#set()对context的修改被认为是针对此velocimacro的本地设置,而不会永久的影响内容。
velocimacro.max.depth = 20 //解析深度
velocimacro.arguments.strict = false //宏参数是否启用严格模式
velocimacro.library.autoreload=false // 控制Velocimacro库是否自动加载。当设置为ture时,对于一个Velocimacro的调用将自动检查原始库是否发生了变化,如果变化将重新加载它。这个属性使得你可以不用重新启动servlet容器而达到重新加载的效果,使用的前提就是resource loader缓存是off状态(file.resource.loader.cache = false)。
资源管理器配置
resource.manager.class = Velocity.Runtime.Resource.ResourceManagerImpl //管理器类名称
resource.manager.cache.class = Velocity.Runtime.Resource.ResourceCacheImpl //缓存器类名称
解析器池配置
parser.pool.class = Velocity.Runtime.ParserPoolImpl //解析池类名称
parser.pool.size = 40 //初始大小
Evaluate配置
directive.evaluate.context.class = Velocity.VelocityContext //上下问类名称
可插入introspector配置
runtime.introspector.uberspect = Velocity.Util.Introspection.UberspectImpl //默认introspector类名称
你可能感兴趣的:(Velocity)