Velocity简介

 
什么是 Velocity
Velocity 是基于 Java 的模板引擎。它允许 Web 页面开发者引用 Java 代码中定义的方法。 Web 设计者可以和 Java 程序开发者并行开发遵循 MVC 模式的 Web 站点。这意味着, Web 设计者可以将精力放在好的 Web 站点设计上,而 Java 程序开发者可以将精力放在编写代码上。 Velocity Java 代码从 Web 页面中分离,使 Web 站点更具长期可维护性,并提供了一种替代 JSP PHP 的方案。
 
VTL(Velocity Template Language) 介绍
VTL 提供一种简单、容易和干静的方法将动态内容合并到 Web 页面。 VTL 使用引用 (references) 将动态内容插入到 Web 页面中。变量是一种引用,可以指向 Java 代码中的定义内容,或者由 Web 页面中的 VTL 语句来获得值。下面是一个可以插入到 HTML 文档的 VTL 语句的例子:
#set( $a = "Velocity" )
VTL 语句以 # 开头,并包含指令 (set) 。变量以 $ 开头,用引号引起。引号可以是单引号,也可以是双引号。前者引用具体的 String 值;后者可以包含 Velocity 引用,例如 ”hello, $name” $name 会用其当前的值替换。上面的例子是将值 Velocity 赋值给变量 a
当变量被赋值后,就可以在 HTML 文档的任何地方引用,下面是 Hello Velocity World! 的例子:
<html>
<body>
#set( $foo = "Velocity" )
Hello $foo World!
</body>
<html>
 
注释
VTL 支持单行注释(以 ## 开始)和多行注释(包括在 #* *# 之间),下面是一个例子:
This text is visible. ## This text is not visible.
This text is visible.
This text is visible. #* This text, as part of a multi-line comment,
is not visible. This text is not visible; it is also part of the
multi-line comment. This text still not visible. *# This text is outside
the comment, so it is visible.
## This text is not visible.
 
引用
VTL 3 种类型的引用:变量、属性和方法。作为一个设计者,必须和 Java 工程师在 VTL 引用的名称(标识符)上一致,以便在模板中使用它们。引用是作为 String 对象处理的。
1 )变量
变量的格式: $VTL 标识符
VTL 标识符以字母开始,由字母、数字、横划线 (-) 或下划线 (_) 组成。变量或者从模板中的 set 指令获得值(如前面的例子),或者 Java 代码(同名变量)中获得值。 Velocity 只处理已定义的变量引用,对于没有定义的变量引用, Velocity 原样返回。例如下面的例子:
#set( $foo = "gibbous" )
$moon = $foo
输出结果是: $moon = gibbous
2 )属性
属性的格式: $VTL 标识符 . VTL 标识符
下面是属性引用的例子:
$customer.Address
$purchase.Total
拿第一例子来说,有两种意思:
l          返回 Hashtable 对象 customer 中键值为 Address 的值
l          $customer.getAddress() 方法引用的缩写( JavaBean 属性的 getter 方法)
至于是哪种情况, Velocity 会做决定,返回合适的值。
3 )方法
方法的格式: $VTL 标识符 ( 参数列表 )
下面是方法引用的例子:
$customer.getAddress()
$purchase.getTotal()
$page.setTitle( "My Home Page" )
$person.setAttributes( ["Strange", "Weird", "Excited"] )
前面两个例子可以缩写成属性引用(如属性引用的例子)。属性引用和方法引用的主要区别是方法引用可以指定参数列表。
4 )正式引用符号: {}
正式引用符号在使用变量引用含糊的地方进行区分。看下面的例子:
#set( $ vice = " klepto" )
Jack is a $vicemaniac.
输出结果是: Jack is a $vicemaniac. $vicemaniac 没有定义,原样输出)
#set( $ vice = " klepto" )
Jack is a ${vice}maniac.
输出结果是: Jack is a kleptomaniac. (使用 正式引用符号将 $vice 和其它文本区分开)
5 Quit 引用符号: !
看下面的例子:
<input type="text" name="email" value="$email"/>
初始时, $email 没有值,所以文本框中会显示值 $email ,而更希望 是空白。下面是使用 Quit 引用符号的例子:
<input type="text" name="email" value="$!email"/>
$email 没有值时, Velocity 会用空串替代 $email
6 )特殊字符转义
对于 $ # 等特殊字符要正常显示,可以使用 / 进行转义, // 转义为 / 。下面是一个例子:
#set( $email = "foo" )
$email
/ $email
// $email
/// $email
输出结果是:
foo
$email
/ foo
/$email
指令 (Directives)
引用允许模板设计者为 Web 站点生成动态内容,而指令使巧妙处理 Java 代码的脚本元素容易使用。
1 #set
格式: #set( LHS = RHS )
l          LHS 可以是变量引用或属性引用
l          RHS 可以是引用、字符串、数字、 ArrayList Map
下面的例子展示了上面的每种 RHS 类型:
#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
#set( $monkey.Number = 123 ) ##number literal
#set( $monkey.Say = ["Not", $my, "fault"] ) ## ArrayList
#set( $monkey.Map = {"banana" : "good", "roast beef" : "bad"}) ## Map
对于 ArrayList Map ,可以使用对应的 Java 方法访问其中的元素值:
$monkey.Say.get(0)
$monkey.Map.get("bannana")
$monkey.Map.banana ## same as above
l          RHS 可以是简单的算术表达式
#set( $value = $foo + 1 ) ## Addition
#set( $value = $bar - 1 ) ## Subtraction
#set( $value = $foo * $bar ) ## Multiplication
#set( $value = $foo / $bar ) ## Division
#set( $value = $foo % $bar ) ## Remainder
算术表达式只支持整型。 / 的结果为整数;如果非整型数值,返回 null
l          如果 RHS 的结果为 null ,是不会赋值给 LHS
看下面的例子:
#set( $criteria = ["name", "address"] )
#foreach( $criterion in $criteria )
    #set( $result = $query.criteria($criterion) )
    #if( $result )
        Query was successful
    #end
#end
上面使用 $result 检查是否执行成功是有问题的。如果第一次执行成功, $result 不为 null ,则后面的执行不管是否成功,检查条件总是成立。改进的方法是在每次执行前初始化为 false
#set( $criteria = ["name", "address"] )
#foreach( $criterion in $criteria )
#set( $result = false )
    #set( $result = $query.criteria($criterion) )
    #if( $result )
        Query was successful
    #end
#end
l          String 文字可以使用双引号或单引号括起。两者的主要区别是双引号中的引用会替换成相应的值,而单引号中的引用原样输出
#set( $directoryRoot = "www" )
#set( $templateName = "index.vm" )
#set( $template = "$directoryRoot/$templateName" )
$template
输出结果是: www/index.vm
如果使用单引号:
#set( $template = '$directoryRoot/$templateName )
输出结果是: $directoryRoot/$templateName
l          使用双引号可以实现字符串的串联,如下面的例子:
      #set( $size = "Big" )
      #set( $name = "Ben" )
      #set($clock = "${size}Tall$name" )
      The clock is $clock.
2 #if / #elseif / #else
#if 指令在条件成立时,显示 #if #end 之间的内容,否则显示 #else #end 之间的内容。下面是一个例子:
#if( $foo )
   <strong>Velocity!</strong>
#end
条件成立有两种情况:
l          如果 $foo boolean ,则 $foo 要为 true
l          否则, $foo 不为 null
#if 指令中可以使用的关系和逻辑符号包括:
l          < <= == >= >
l          &&(and) ||(or) !(not)
3 )循环: foreach
下面是一个例子:
<ul>
#foreach( $product in $allProducts )
    <li>$product</li>
#end
</ul>
$allProducts 的内容可以是 Vector Hashtable ArrayList ,每次取出一个值赋值给 $product ;返回的值是一个 Java 对象,可以用来引用具体的方法。下面的例子假设 $allProducts Hashtable 对象:
<ul>
#foreach( $key in $allProducts.keySet() )
    <li>Key: $key -> 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 表示循环计数的内部变量,缺省开始值为 1 。该设置在 velocity.properties 文件中定义:
# 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
可以在 #foreach 指令中使用范围操作符 [n..m] ,其中 n m 必须是整型:
First example:
#foreach( $foo in [1..5] )
$foo
#end
Second example:
#foreach( $bar in [2..-2] )
$bar
#end
Third example:
#set( $arr = [0..1] )
#foreach( $i in $arr )
$i
#end
输出结果是:
First example:
1 2 3 4 5
Second example:
2 1 0 -1 -2
Third example:
0 1
4 #include
#include 指令导入本地文件到 #include 指令定义的地方。导入的文件内容不会被模板引擎解析。出于安全考虑,导入的文件应该放在 TEMPLATE_ROOT 目录下。一次可以导入多个文件,文件名之间用逗号分隔;并且通常使用变量引用来替代文件名。下面是一个例子:
#include( "greetings.txt", $seasonalstock )
5 #parse
#parse 指令允许导入一个包含 VTL 的本地文件,并由模板引擎进行解析。 #parse 指令导入的文件必须放在 TEMPLATE_ROOT 目录下,并且一次只能导入一个文件。允许在 Velocity 模板中嵌套执行 #parse 指令。最大深度由 velocity.properties 文件中的 parse_directive.maxdepth 定义。下面是一个例子:
Count down.
#set( $count = 8 )
#parse( "parsefoo.vm" )
All done with dofoo.vm!
包含的 parsefoo.vm 文件如下:
$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!
6 #stop
#stop 指令停止模板引擎的执行并返回。这在 Debug 时很有用。
7 #macro
#macro 指令允许定义一段重复使用的 VTL 模板(称 Velocimacros )。
l          Velocimacros 可以有 0 或多个参数。下面是一个例子:
#macro( tablerows $color $somelist )
#foreach( $something in $somelist )
    <tr><td bgcolor=$color>$something</td></tr>
#end
#end
这个叫 tablerows Velocimacro 2 个参数:一个 color 和一个 array 。下面的代码包含对
tablerows 的调用:
#set( $greatlakes = ["Superior","Michigan","Huron","Erie","Ontario"] )
#set( $color = "blue" )
<table>
    #tablerows( $color $greatlakes )
</table>
输出结果为:
<table>
    <tr><td bgcolor="blue">Superior</td></tr>
    <tr><td bgcolor="blue">Michigan</td></tr>
    <tr><td bgcolor="blue">Huron</td></tr>
    <tr><td bgcolor="blue">Erie</td></tr>
    <tr><td bgcolor="blue">Ontario</td></tr>
</table>
l          Velocimacros 可以在 VTL 模板中定义为 inline ,这样对其它的 VTL 模板是无效的;要使 Velocimacros 在所有 VTL 模板中共享,可以将 Velocimacros 定义在 Velocimacros 模板库(全局)中。
l          Velocimacros 属性在velocity.properties文件中定义,提供实现 Velocimacros 的灵活性:
velocimacro.library = VM_global_library.vm
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.library.autoreload = false
velocimacro.library :定义逗号分隔的 Velocimacros 全局模板库,缺省是 VM_global_library.vm ,可以增加自定义的模板库;
velocimacro.permissions.allow.inline :指定是否允许在 VTL 模板中定义 Velocimacros ,缺省是 true (允许);
velocimacro.permissions.allow.inline.to.replace.global :指定是否允许 inline 定义的 Velocimacros 替换同名的全局 Velocimacros ,缺省是 false (不允许);
velocimacro.permissions.allow.inline.local.scope :指定 inline 定义是否是定义的模板中可见,缺省是 false
velocimacro.context.localscope :指定 context 内容是否是本地范围的,缺省是 false ;如果设为 true ,则使用 #set 指令对 context 做的修改只在本地范围有效,不会永久性的影响 context
velocimacro.library.autoreload 指定是否自动装载 Velocimacros 模板库,缺省是 false ;如果设为 true ,则在调用 Velocimacros 模板库中的 Velocimacro 时,会检查模板库是否更新,并在需要时重新装载;使用前提是 file.resource.loader.cache = false ;该属性应该在开发时使用,而不是产品阶段;
l          Velocimacros 必须在第一次使用之前进行定义。因此 #parse 指令包含 inline 定义的 Velocimacros 的模板会有问题,简单的解决方法就是将 Velocimacros 定义到模板库中,以便 Velocity 启动时装载。
l          引用作为 Velocimacros 的参数时,是使用 by name 形式的,这意味在 Velocimacros 内部每次使用时才会获得其值
l          Velocimacros 的不能作为参数传递给另一个 Velocimacros ,如:
#center( #bold("hello") ) ##invalid
你可以采用下面的形式达到同样的目的:
#center("#bold( 'hello' )"  ) ##right
下面是一个嵌套调用的例子:
#macro( inner $foo )
 inner : $foo
#end
#macro( outer $foo )
   #set($bar = "outerlala")
   outer : $foo
#end
#set($bar = 'calltimelala')
#outer( "#inner($bar)" )
输出的结果是:Outer : inner : outerlala
因为 参数以 by name 形式传递,在 #outer 内部先设置 $bar 的值,再调用 #inner
 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值