用户指南 – 内容
关于本指南
Velocity用户指南旨在帮助页面设计人员和内容提供者熟悉Velocity及其简单而强大的脚本语言Velocity模板语言(VTL)的语法。本指南中的许多示例涉及使用Velocity在网站中嵌入动态内容,但所有VTL示例同样适用于其他页面和模板。
感谢您选择Velocity!
什么是Velocity?
Velocity是一个基于Java的模板引擎。它允许网页设计者引用在Java代码中定义的方法。Web设计人员可以与Java程序员并行工作,根据模型 – 视图 – 控制器(MVC)模型开发网站,这意味着网页设计人员可以专注于创建设计良好的网站,程序员可以专注于编写顶层 – 代码。Velocity将Java代码从网页中分离出来,使得网站在长期运行中更易于维护,并为Java Server Page(JSP)或PHP提供了一种可行的替代方案。
Velocity可用于生成网页,SQL,PostScript和其他模板输出。它既可以作为一个独立的实用程序来生成源代码和报告,也可以作为其他系统的集成组件使用。完成后,Velocity将为Turbine Web应用程序框架提供模板服务。Velocity + Turbine将提供模板服务,可以根据真正的MVC模型开发Web应用程序。
Velocity能为我做什么?
泥浆店示例
假设你是专门销售泥浆的在线商店的页面设计师。我们称之为“在线泥浆商店”。生意兴隆。客户订购各种类型和数量的泥浆。他们使用他们的用户名和密码登录到您的网站,以便他们查看他们的订单并购买更多泥浆。现在,兵马俑泥正在出售,这是非常受欢迎的。您的少数客户会定期购买Bright Red Mud,这款产品也正在销售中,虽然不太受欢迎,通常会降级到您的网页边缘。有关每个客户的信息都会在您的数据库中进行跟踪,因此总有一天会出现问题:为什么不使用Velocity将泥浆特殊交易针对那些对这些泥浆最感兴趣的客户?
利用Velocity可以轻松为您的在线访问者定制网页。作为The Mud Room的网站设计师,您希望制作客户在登录您的网站后看到的网页。
您会与贵公司的软件工程师会面,并且每个人都同意$客户将持有与当前登录的客户有关的信息,$ mudsOnSpecial将成为目前所有类型的销售。在$鞭击对象包含与推广帮助的方法。对于手头的任务,让我们只关心这三个参考。请记住,您不必担心软件工程师如何从数据库中提取必要的信息,您只需要知道它的工作原理。这可以让你继续工作,让软件工程师继续他们的工作。
您可以在网页中嵌入以下VTL语句:
<html> <body> $ customer.Name! <表> #foreach($ mud in $ mudsOnSpecial) #if($ customer.hasPurchased($ mud)) <tr> <td> $ flogger.getPromo($ mud) </ td> </ tr> #结束 #结束 </ table> </ body> </ html>
关于foreach声明的确切细节将在不久后进行更深入的描述; 重要的是这个简短的脚本可以在你的网站上产生的影响。当一个喜欢明亮红色泥浆的顾客登陆时,以及明亮的红色泥浆正在销售,这是客户将看到的,突出显示的。如果另一位有着长期购买兵马俑历史的客户登录,则通知Terracotta泥浆销售将成为前沿和中心。Velocity的灵活性是巨大的,只受到你的创造力的限制。
在VTL参考文档是许多其他的速度元素,它们共同给你,你需要让你的网站网页的力量和柔韧性的存在。随着你对这些元素更加熟悉,你将开始释放Velocity的力量。
Velocity模板语言(VTL):介绍
速度模板语言(VTL)旨在提供最简单,最简单,最简洁的方式将动态内容合并到网页中。即使是一个很少或没有编程经验的网页开发人员,也应该很快就能够使用VTL将动态内容合并到网站中。
VTL使用引用来将动态内容嵌入到网站中,而变量是一种引用类型。变量是一种引用类型,可以引用Java代码中定义的某些内容,也可以从网页中的VTL 语句获取它的值。以下是可以嵌入到HTML文档中的VTL语句的示例:
#set($ a =“Velocity”)
与所有VTL语句一样,此VTL语句以#字符开头,并包含一个指令:set。当在线访问者请求您的网页时,Velocity模板引擎将搜索您的网页以查找所有#字符,然后确定VTL语句的开始标记以及与VTL无关的#个字符中的哪一个。
该#字符后跟一个指令,设定。该组指令使用的表达式(用括号括起来) -其分配的方程式值的变量。变量列在左侧,其值在右侧; 两个由一个=字符分隔。
在上面的例子中,变量是$ a,值是Velocity。像所有引用一样,这个变量以$字符开头。字符串值总是用引号引起来,不论是单引号还是双引号。单引号将确保引用的值将按原样分配给引用。双引号允许您使用速度引用和指令进行插值,例如“Hello $ name”,其中$ name将被当前值替换,然后将该字符串文字分配给该元素的左手边=
下面的经验法则可能对于更好地理解Velocity如何工作有用:参考文献以$开头,用于获取某些内容。指令以#开始,并用于执行某些操作。
在上面的例子中,# set用于为变量赋值。然后可以在模板中使用变量$ a来输出“Velocity”。
你好速度世界!
一旦将一个值分配给一个变量,就可以在HTML文档的任何位置引用该变量。在以下示例中,将值分配给$ foo并稍后参考。
<html> <body> #set($ foo =“Velocity”) 您好$ foo世界! </ body> </ html>
结果是打印出“Hello Velocity World!”的网页。
要使包含VTL指令的语句更具可读性,我们鼓励您在新行上启动每个VTL语句,尽管您不需要这样做。该组指令将更为详细地重新审视以后。
评论
评论允许包含描述性文本,而不将其放置在模板引擎的输出中。评论是提醒自己并向其他人解释你的VTL语句正在做什么或者你认为有用的任何其他目的的有用方式。以下是VTL中的评论示例。
##这是一行注释。
单行注释以##开始,并在行尾结束。如果您打算写几行评论,则不需要有大量单行注释。多行注释,这首先#和结束#,可用来处理这种情况。
这是多行注释之外的文字。 在线访问者可以看到它。 #* 因此开始了多行评论。在线访问者不会 请参阅此文本,因为速度模板引擎会 忽略它。 *# 这是多行评论之外的文字; 它是可见的。
以下是一些例子来说明单行和多行注释的工作原理:
这段文字是可见的。##这段文字不是。 这段文字是可见的。 这段文字是可见的。#*这个文本,作为多行的一部分 评论,是不可见的。此文字不可见; 也是 是多行评论的一部分。这段文字还没有 可见。*#此文字在评论之外,因此它是可见的。 ##此文字不可见。
还有第三种评论,即VTL注释块,它可以用来存储任何想要在模板中追踪的额外信息(例如,javadoc风格的作者和版本信息):
#** 这是一个VTL注释块和 可以用来存储这些信息 作为文档的作者和版本 信息: @作者约翰·多伊 @version 5 *#
参考
VTL中有三种类型的引用:变量,属性和方法。作为使用VTL的设计师,您和您的工程师必须就引用的具体名称达成一致,以便您可以在模板中正确使用它们。
变量
变量的简写符号由一个前导的“$”字符和一个VTL 标识符组成。VTL标识符必须以字母字符(a .. z或A .. Z)开头。其余字符仅限于以下类型的字符:
- 字母(a .. z,A .. Z)
- 数字(0 .. 9)
- 下划线(“_”)
以下是VTL中有效变量引用的一些示例:
$ FOO $ mudSlinger $泥投石 $ mud_slinger $ mudSlinger1
当VTL引用变量(如$ foo)时,变量可以从模板中的set指令或Java代码中获取其值。例如,如果Java变量$ foo在请求模板时具有值栏,则bar将替换网页上$ foo的所有实例。或者,如果我包含该声明
#set($ foo =“bar”)
对于遵循此指令的$ foo的所有实例,输出都是相同的。
属性
VTL引用的第二种风格是属性,属性具有独特的格式。速记符号包含一个前导$字符,后跟一个VTL标识符,后跟一个点字符(“。”)和另一个VTL标识符。这些是VTL中有效属性引用的示例:
$ customer.Address $ purchase.Total
以第一个示例$ customer.Address为例。它可以有两个含义。它可以表示:查找标识为客户的散列表并返回与关键字Address关联的值。但$ customer.Address也可以引用一个方法(引用方法的引用将在下一节讨论); $ customer.Address可能是编写$ customer.getAddress()的缩写方式。当您的页面被请求时,Velocity将确定这两种可能性中的哪一种是有意义的,然后返回适当的值。
方法
Java代码中定义了一种方法,可以执行一些有用的操作,例如运行计算或作出决定。方法是由一个前导的“$”字符组成的引用,后跟一个VTL标识符,后跟一个VTL 方法体。VTL方法体由VTL标识符,后跟左括号字符(“(”),后跟可选参数列表,后跟右括号字符(“)”)组成。这些是VTL中有效方法引用的示例:
$ customer.getAddress() $ purchase.getTotal() $ page.setTitle(“我的主页”) $ person.setAttributes([“奇怪”,“奇怪”,“兴奋”])
前两个示例 – $ customer.getAddress()和$ purchase.getTotal() – 可能类似于上面的属性部分中使用的$ customer.Address和$ purchase.Total。如果你猜这些例子必须以某种方式相关,你是对的!
VTL属性可以用作VTL方法的简写符号。Property $ customer.Address与使用Method $ customer.getAddress()具有完全相同的效果。通常最好在可用时使用Property。属性和方法之间的主要区别是您可以为Method指定参数列表。
速记符号可用于以下方法
$ sun.getPlanets() $ annelid.getDirt() $ album.getPhoto()
我们可能希望这些方法能够返回属于太阳的行星名称,喂食我们的蚯蚓,或从专辑中获取照片。只有长符号适用于以下方法。
$ sun.getPlanet([“Earth”,“Mars”,“Neptune”]) ##无法通过$ sun.Planets传递参数列表 $ sisyphus.pushRock() ## Velocity假设我的意思是$ sisyphus.getRock() $ book.setTitle(“致敬加泰罗尼亚”) ##无法传递参数
所有数组引用都被视为固定长度列表。这意味着你可以在数组引用上调用java.util.List方法和属性。所以,如果你有一个对数组的引用(假设这是一个带有三个值的String []),你可以这样做:
$ myarray.isEmpty()或$ myarray.empty $ myarray.size() $ myarray.get(2) $ myarray.set(1,'test')
Velocity还支持可变参数方法。类似azpublic void setPlanets(String... planets)
或甚至public void setPlanets(String[] planets)
可以在模板中调用时接受任意数量的参数。
$ sun.setPlanets('地球','火星','海王星') $ sun.setPlanets( '水星') $ sun.setPlanets() ##会传入一个空的零长度的数组
从Velocity 2.0开始,方法调用现在提供了所有Java基本内建类型之间的隐式转换:数字,布尔值和字符串。
属性查找规则
如前所述,属性通常引用父对象的方法。找出哪种方法符合要求的属性时,Velocity非常聪明。它根据几个已建立的命名约定尝试不同的替代方案。确切的查找顺序取决于属性名称是否以大写字母开头。对于小写名称,例如$ customer.address,序列是
- 的getAddress()
- 的getAddress()
- 获得(“地址”)
- isAddress()
对于像$ customer.Address这样的大写属性名称,它稍有不同:
- 的getAddress()
- 的getAddress()
- 获得(“地址”)
- isAddress()
渲染
当每个引用(无论是变量,属性还是方法)生成的最终值在呈现为最终输出时都会转换为String对象。如果有一个表示$ foo的对象(比如一个Integer对象),那么Velocity将调用它的.toString()
方法将该对象解析为一个String。
索引符号
使用表单的符号$foo[0]
可以用来访问对象的给定索引。这种形式与在给定对象上调用get(Object)方法是同义的$foo.get(0)
,并且本质上为这些操作提供了句法速记。由于这只是简单地调用get方法,所有以下都是有效的用途:
$ foo [0] ## $ foo需要一个Integer查找 $ foo [$ i] ##使用另一个引用作为索引 $ foo [“bar”] ##传递一个字符串,其中$ foo可能是一个Map
括号内的语法也适用于Java数组,因为Velocity将数组包装在访问对象中,该访问对象提供了get(Integer)
返回指定元素的方法。
括号内的语法在任何地方.get
都是有效的,例如:
$ foo.bar [1] .junk $ foo.callMethod()[1] $ foo的[ “苹果”] [4]
引用也可以使用索引符号来设置,例如:
#set($ foo [0] = 1) #set($ foo.bar [1] = 3) #set($ map [“apple”] =“orange”)
指定的元素用给定的值设置。Velocity首先尝试元素上的’set’方法,然后’put’进行分配。
正式参考符号
上面列出的例子使用了引用的简写符号,但也有一个引用的正式符号,如下所示:
$ { mudSlinger } $ { customer 。地址} $ { 购买。getTotal ()}
在几乎所有情况下,您都将使用简写符号作为参考,但在某些情况下,正确的符号需要进行正确的处理。
假设你正在建造一个句子,其中$ vice将被用作句子名词中的基本单词。目标是允许某人选择基本词并产生以下两个结果中的一个:“杰克是pyromaniac。” 或者“杰克是个鬼怪”。使用速记符号将不足以完成此任务。考虑下面的例子:
杰克是个副手。
这里有不明确的地方,Velocity假设$ vicemaniac而不是$ vice,是您要使用的标识符。找不到$ vicemaniac的价值,它会返回$ vicemaniac。使用正式表示法可以解决此问题。
杰克是一个$ { 副}疯子。
现在Velocity知道$ vice,而不是$ vicemaniac,是参考。当引用与模板中的文本直接相邻时,正式表示法通常很有用。
安静的参考符号
当Velocity遇到未定义的引用时,其正常行为是输出引用的图像。例如,假设以下参考显示为VTL模板的一部分。
<input type =“text”name =“email”value =“$ email”/>
当表单初始加载时,变量引用$ email没有值,但是您希望空白文本字段的值为“$ email”。使用安静的参考符号可以避免Velocity的正常行为; 而不是在VTL 中使用$电子邮件,您可以使用$!电子邮件。所以上面的例子看起来像下面这样:
<input type =“text”name =“email”value =“$!email”/>
现在,当表单初始加载并且$ email仍然没有值时,将输出一个空字符串而不是“$ email”。
正式和安静的参考符号可以一起使用,如下所示。
<input type =“text”name =“email”value =“$!{email}”/>
严格的参考模式
Velocity 1.6引入了严格参考模式的概念,该模式通过将速度配置属性’runtime.references.strict’设置为true来激活。此设置的一般意图是使Velocity在未定义或含糊不清的情况下更加严格,类似于编程语言,可能更适合Velocity的某些用途。在这种未定义或模棱两可的情况下,Velocity会抛出异常。以下讨论概述了严格行为与传统行为不同的情况。
有了这个设置,引用必须明确地放在上下文中,或者用#set指令定义,否则Velocity会抛出异常。上下文中值为null的引用不会产生异常。此外,如果尝试在未定义指定方法或属性的引用内调用对象的方法或属性,则Velocity将引发异常。如果尝试调用空值的方法或属性,也是如此。
在下面的例子中定义了$ bar,但$ foo不是,所有这些语句都会抛出一个异常:
$ foo ## 异常 #组($ 栏 = $ FOO )## 异常 #如果($ FOO == $ 棒)#结束## 异常 #的foreach ($ 项目 在 $ FOO )#结束## 异常
另外,以下语句显示了Velocity在尝试调用不存在的方法或属性时会抛出异常的示例。在这些例子中,$ bar包含一个对象,它定义了一个返回字符串的属性’foo’和一个返回null的’retnull’。
$ bar.bogus ## $ bar不提供属性伪造,异常 $ bar.foo.bogus ## $ bar.foo不提供属性伪造,异常 $ bar.retnull.bogus ##不能调用null,Exception </ pre>的属性
通常严格的引用行为适用于所有使用引用的情况,除了#if指令中的特殊情况。如果在没有任何方法或属性的情况下在#if或#elseif指令内使用引用,并且如果不将它与另一个值进行比较,则允许使用未定义的引用。此行为提供了一种简单的方法来测试在模板中使用它之前是否定义了引用。在下面的例子中,$ foo没有定义,语句不会抛出异常。
#if($ foo)#end ## False #if(!$ foo)#end ## True #if($ foo && $ foo.bar)#end ## False和$ foo.bar不会被评估 #if($ foo && $ foo ==“bar”)#end ## False和$ foo ==“bar”无法评估 #if($ foo1 || $ foo2)#end ## False $ foo1和$ foo2未定义
严格模式要求在#if指令中比较>,<,> =或<=是有意义的。此外,#foreach的参数必须是可迭代的(此行为可以使用property directive.foreach.skip.invalid进行修改)。最后,未定义的宏引用也会在严格模式下抛出异常。
Velocity试图呈现但评估为null的引用将导致异常。为了在这种情况下简单地渲染任何东西,可以在引用之前加上’$!’。而不是’$’,类似于非严格模式。请记住,这与上下文中不存在的引用不同,当尝试以严格模式呈现它时,它始终会引发异常。例如,在$ foo下的上下文中的值为null
这是$ foo ##引发异常,因为$ foo为空 这是$!foo ##呈现为“this is”,没有例外 这是$!bogus ## bogus不在上下文中,因此引发异常
案例替换
现在你已经熟悉了引用,你可以开始在你的模板中有效地应用它们。速度引用利用了模板设计人员会发现易于使用的一些Java原则。例如:
$ FOO $ foo.getBar() ## 是相同的 $ foo.Bar $ data.setUser(“jon”) ## 是相同的 #set($ data.User =“jon”) $ data.getRequest().getServerName() ## 是相同的 $ data.Request.ServerName ## 是相同的 $ { data 。请求。ServerName }
这些例子说明了相同参考文献的替代用途。Velocity利用Java的内省和bean特性来解析Context中的两个对象的引用名称以及对象方法。可以在模板的任何位置嵌入和评估参考。
基于Sun Microsystems定义的Bean规范建模的Velocity区分大小写; 然而,它的开发人员努力在任何可能的地方捕捉和纠正用户错误。当方法getFoo()在模板中被引用时$bar.foo
,Velocity将首先尝试$getfoo
。如果失败了,它会尝试$getFoo
。同样,当模板引用时$bar.Foo
,Velocity会首先尝试$ getFoo(),然后尝试getfoo()。
注意:对模板中实例变量的引用未解析。只有对JavaBean getter / setter方法的属性等价物的引用才被解析(即$foo.Name
,解析为Foo类的getName()
实例方法,但不解析为Foo的公共Name
实例变量)。
指令
引用允许模板设计人员为网站生成动态内容,而指令 – 易于使用的脚本元素可用于创造性地操纵Java代码的输出 – 允许网页设计人员真正负责网页的外观和内容现场。
指令始终以a开头#
。与引用类似,指令的名称可以用a {
和}
符号括起来。这对紧跟文本的指令很有用。例如,以下产生一个错误:
#如果($ 一个== 1 )真够#elseno 方式!#结束
在这种情况下,使用括号#else
从行的其余部分分开。
#如果($ 一个== 1 )真够#{ 其他} 没办法!#结束
设置
所述#SET指令用于设置的参考值。值可以分配给变量引用或属性引用,并且这发生在括号中,如下所示:
#set($ primate =“monkey”) #set($ customer.Behavior = $ primate)
作业的左侧(LHS)必须是变量引用或属性引用。右侧(RHS)可以是以下类型之一:
- 变量参考
- 字符串字面量
- 属性参考
- 方法参考
- 数字文字
- 数组列表
- 地图
这些例子展示了上述每种类型:
#set($ monkey = $ bill)##变量引用 #set($ monkey.Friend =“monica”)##字符串 #set($ monkey.Blame = $ whitehouse.Leak)##属性参考 #set($ monkey.Plan = $ spindoctor.weave($ web))##方法参考 #set($ monkey.Number = 123)##数字文字 #set($ monkey.Say = [“Not”,$ my,“fault”])## ArrayList #set($ monkey.Map = {“banana”:“good”,“烤牛肉”:“bad”})## Map
注:对于ArrayList示例,使用[..]运算符定义的元素可以使用ArrayList类中定义的方法访问。因此,例如,您可以使用$ monkey.Say.get(0)访问上面的第一个元素。
同样,对于Map示例,{}运算符中定义的元素可以使用Map类中定义的方法访问。因此,例如,您可以使用$ monkey.Map.get(“banana”)来访问上面的第一个元素,以返回字符串’good’,甚至$ monkey.Map.banana以返回相同的值。
RHS也可以是一个简单的算术表达式:
#set($ value = $ foo + 1) #set($ value = $ bar - 1) #set($ value = $ foo * $ bar) #set($ value = $ foo / $ bar)
如果RHS是一个评估为空的属性或方法引用,它将不会被分配给LHS。根据Velocity的配置方式,通常不可能通过这种机制从上下文中删除现有的引用。(请注意,通过更改其中一个Velocity配置属性可以允许这样做)。这可能会让Velocity的新手感到困惑。例如:
#set($ result = $ query.criteria(“name”)) 第一个查询的结果是$ result #set($ result = $ query.criteria(“address”)) 第二个查询的结果是$ result
如果$ query.criteria(“name”)返回字符串“bill”,并且$ query.criteria(“address”)返回null,则上面的VTL将呈现如下所示:
第一个查询的结果是账单 第二个查询的结果是账单
这往往会混淆谁建造新人#foreach循环,即试图#SET通过属性或方法引用的参考,然后立即测试与该参考#如果指令。例如:
#set($ criteria = [“name”,“address”]) #foreach($ criteria中的$标准) #set($ result = $ query.criteria($ criterion)) #if($结果) 查询成功 #结束 #结束
在上面的例子中,依靠$ result的评估来判断查询是否成功并不明智。之后$结果已#SET(加入上下文),它不能被重新设置为空(从上下文移除)。本文后面会介绍#if和#foreach指令的细节。
解决这个问题的方法之一是将$ result预设为false。然后如果$ query.criteria()调用失败,你可以检查。
#set($ criteria = [“name”,“address”]) #foreach($ criteria中的$标准) #set($ result = false) #set($ result = $ query.criteria($ criterion)) #if($结果) 查询成功 #结束 #结束
与其他一些Velocity指令不同,# set指令没有#end语句。
字面
使用#set指令时,用双引号字符括起来的字符串文字将被解析并呈现,如下所示:
#set($ directoryRoot =“www”) #set($ templateName =“index.vm”) #set($ template =“$ directoryRoot / $ templateName”) $模板
输出将是
WWW / index.vm
但是,当字符串文字用单引号字符括起来时,它不会被解析:
#set($ foo =“bar”) $ FOO #set($ blargh ='$ foo') $ blargh
这呈现为:
酒吧 $ FOO
默认情况下,Velocity提供了使用单引号来呈现未解析文本的功能。该默认可以通过编辑来改变velocity.properties
这样stringliterals.interpolate=false
。
或者,#[[不要解析我!]]#语法允许模板设计人员在VTL代码中轻松使用大量未解释和未解析的内容。这对于转义多个指令或转义部分具有特别的用处,这些部分的内容可能是无效的(因此无法分析)VTL。
#[ #foreach($ woogie in $ boogie) $ woogie什么也不会发生 #结束 ]]#
呈现为:
#foreach($ woogie in $ boogie) $ woogie什么也不会发生 #结束
条件
如果/ ElseIf /
Velocity中的#if指令允许在网页生成时包含文本,条件是if语句为true。例如:
#if($ foo) <strong>速度!</强> #结束
对变量$ foo进行评估以确定它是否为真,这将在以下情况下发生:
- $ foo是一个布尔值(true / false),它有一个真值
- $ foo的是一个字符串或一个集合,其不为空和不为空
- $ foo是一个不等于零的数字
- $ foo是一个不为空的对象(除了一个字符串,一个数字或一个集合)
(请注意,这是默认行为,但Velocity可以配置为跳过布尔值和无效值之外的所有检查)。
请记住,Velocity上下文仅包含Objects,所以当我们说’boolean’时,它将被表示为布尔(类)。即使对于返回的方法也是如此boolean
– 内省基础结构将返回一个Boolean
具有相同逻辑值的值。
如果评估为真,则#if和#end语句之间的内容将成为输出。在这种情况下,如果$ foo为真,则输出将是:“Velocity!”。相反,如果$ foo有一个空值,或者如果它是一个布尔值false,则该语句的计算结果为false,并且没有输出。
一个#elseif或#else伪元件可以与被使用的#if元件。请注意,速度模板引擎将停止在发现为真的第一个表达式上。在下面的例子中,假设$ foo的值为15,$ bar的值为6。
#if($ foo <10) **去北** #elseif($ foo == 10) **去东** #elseif($ bar == 6) **去南** #其他 **向西走** #结束
在这个例子中,$ foo大于10,所以前两个比较失败。接下来的$ bar与6进行比较,这是真的,所以输出是Go South。
关系和逻辑运算符
Velocity使用等效运算符来确定变量之间的关系。下面是一个简单的例子来说明如何使用等价操作符。
#set($ foo =“脱氧核糖核酸”) #set($ bar =“ribonucleic acid”) #if($ foo == $ bar) 在这种情况下,他们显然不是等同的。所以... #其他 它们不是等价的,这将是输出。 #结束
请注意,==的语义与Java稍有不同,其中==只能用于测试对象相等性。在Velocity中,等效运算符可用于直接比较数字,字符串或对象。当对象是不同的类时,通过调用toString()
每个对象然后进行比较来获得字符串表示。
Velocity也具有逻辑AND,OR和NOT运算符。以下是演示使用逻辑AND,OR和NOT运算符的示例。
##逻辑与 #if($ foo && $ bar) ** 这个和那个** #结束
如果$ foo和$ bar都为真,#if()指令只会计算为真。如果$ foo为false,则表达式将评估为false; $ bar不会被评估。如果$ foo为true,则Velocity模板引擎将检查$ bar的值; 如果$ bar是真的,那么整个表达式就是真的,这就成为输出。如果$ bar为假,那么将不会有输出,因为整个表达式都是假的。
逻辑OR运算符的工作方式是相同的,除非只有一个引用需要评估为true才能使整个表达式被视为真实。考虑下面的例子。
##逻辑或 #if($ foo || $ bar) **这个或那个** #结束
如果$ foo为true,则Velocity模板引擎无需查看$ bar ; 不管$ bar是真还是假,表达式都是真的,并且这个OR将被输出。如果$ foo为false,则必须检查$ bar。在这种情况下,如果$ bar也是false,则表达式的计算结果为false,并且没有输出。另一方面,如果$ bar为真,则整个表达式为真,并且输出是This OR That
使用逻辑NOT运算符,只有一个参数:
##逻辑NOT #if(!$ foo) **不是那个** #结束
这里,if $ foo是true,那么!$ foo的计算结果为false,并且没有输出。如果$ foo为假,那么!$ foo的计算结果为true,而不是输出。注意不要将它与安静的引用$!foo混淆,这是完全不同的。
有所有的逻辑运算符,包括的文本版本当量,NE,和,或者,不,GT,GE,LT,和文件。
另一个有用的说明。当您希望在#else指令后立即包含文本时,您需要使用大括号将括号直接指向该指令以区别于以下文本。(任何指令都可以用大括号分隔,尽管这对#else最有用)。
#如果( $ FOO == $ 条)这是真的!#{ else } 不是!#结束
循环
Foreach
该#foreach元素允许循环。例如:
<UL> #foreach($ allProducts中的$ product) <li> $ product </ li> #结束 </ UL>
此#foreach循环导致列表中的所有产品(目标)循环使用$ allProducts列表(对象)。每次循环时,$ allProducts中的值都放入$ product变量中。
$ allProducts变量的内容是一个Vector,一个Hashtable或一个数组。分配给$ product变量的值是一个Java对象,可以像这样从变量中引用。例如,如果$ product实际上是Java中的Product类,则可以通过引用$ product.Name方法(即:$ Product.getName())来检索其名称。
可以说$ allProducts是一个Hashtable。如果您想要检索Hashtable的键值以及Hashtable中的对象,可以使用如下代码:
<UL> #foreach($ key in $ allProducts.keySet()) <li>键:$ key - >值:$ allProducts.get($ key)</ li> #结束 </ UL>
Velocity提供了一种简单的方法来获得循环计数器,以便您可以执行以下操作:
<表> #foreach($ customerList中的$ customer) <tr> <td> $ foreach.count </ td> <td> $ customer.Name </ td> </ tr> #结束 </ TABLE>
Velocity现在还提供了一种简单的方法来判断您是否处于循环的最后一次迭代中:
#的foreach ( $ 客户 在 $ customerList ) $ 客户。名称#如果( $ 的foreach 。hasNext ),#结束 #结束
如果你想要#foreach循环的从零开始的索引,你可以使用$ foreach.index而不是$ foreach.count。同样,提供$ foreach.first和$ foreach.last以赞美$ foreach.hasNext。如果要访问外部#foreach循环的这些属性,可以直接通过$ foreach.parent或$ foreach.topmost属性(例如$ foreach.parent.index或$ foreach.topmost.hasNext)引用它们。
可以设置循环可以执行的最大允许次数。默认情况下没有最大值(由0或更小的值表示),但可以将其设置为velocity.properties
文件中的任意数字。这对于故障安全是有用的。
#允许的最大循环数。 directive.foreach.maxloops = -1
如果你想停止从你的模板中的foreach循环,你现在可以使用#break指令在任何时候停止循环:
##仅列出前5位客户 #foreach($ customerList中的$ customer) #if($ foreach.count> 5) #打破 #结束 $ customer.Name #结束
包括
该的#include脚本元素允许模板设计者导入本地文件,然后将其插入到其中的位置的#include指令定义。该文件的内容不通过模板引擎呈现。出于安全原因,要包含的文件只能在TEMPLATE_ROOT下。
#include(“one.txt”)
#include指令引用的文件用引号引起来。如果包含多个文件,它们应该用逗号分隔。
#include(“one.gif”,“two.txt”,“three.htm”)
被包含的文件不需要按名称引用; 事实上,通常最好使用一个变量而不是文件名。这对于根据提交页面请求时确定的标准来定位输出会很有用。这是一个显示文件名和变量的例子。
#include(“greetings.txt”,$ seasonalstock)
解析
该#parse脚本元素允许模板设计者导入包含VTL的本地文件。Velocity将解析VTL并渲染指定的模板。
#parse(“me.vm”)
像#include指令一样,# parse可以采用变量而不是模板。#parse引用的任何模板都必须包含在TEMPLATE_ROOT下。与#include指令不同,# parse只会使用一个参数。
VTL模板可以有#parse语句引用模板,而模板又有#parse语句。默认情况下设置为10,允许用户自定义的最大数量的#parse引用可以从单个模板中发生,该指令的directive.parse.max.depth行。(注意:如果文件中缺少directive.parse.max.depth属性,Velocity会将此默认值设置为10.)例如,如果模板包含以下行,则允许递归:velocity.properties
velocity.properties
dofoo.vm
倒数。 #set($ count = 8) #parse(“parsefoo.vm”) 全部用dofoo.vm完成!
它会引用parsefoo.vm
可能包含以下VTL 的模板:
$计数 #set($ count = $ count - 1) #if($ count> 0) #parse(“parsefoo.vm”) #其他 全部用parsefoo.vm完成! #结束
在“倒计时”之后。显示,速度通过parsefoo.vm
,从8开始递减计数。当计数达到0时,它将显示“全部用parsefoo.vm完成!” 信息。此时,Velocity将返回dofoo.vm
并输出“全部用dofoo.vm完成!” 信息。
打破
该#break指令停止当前执行范围的任何进一步渲染。一个“执行范围”本质上是任何含有内容的指令(即#foreach,#parse,#evaluate,#define,#macro或#@ somebodymacro)或任何“根”范围(即template.merge(…) Velocity.evaluate(…)或velocityEngine.evaluate(…))。与#stop不同,#break只会停止最内层的即时作用域,而不是全部。
如果您希望跳出不一定是最直接的特定执行范围,那么您可以将范围控制参考(即$ foreach,$ template,$ evaluate,$ define,$ macro或$ somebodymacro)作为参考传递给#break的参数。(例如#break($宏))。这将停止渲染所有范围达到指定的范围。在相同类型的嵌套范围内时,请记住,您始终可以通过$访问父级.parent或$.top并将它们传递给#break(例如#break($ foreach.parent)或#break($ macro.topmost))。
停止
该#停止指令停止模板的任何进一步的渲染和执行。即使指令嵌套在通过#parse访问的另一个模板中,或者位于速度宏中,也是如此。生成的合并输出将包含达到#stop指令遇到的所有内容。这对于模板的早期退出很方便。为了调试的目的,你可以提供一个消息参数(例如#stop(’$ foo不在上下文中)),当停止命令完成时,它将写入日志(当然是DEBUG级别)。
评估
该#evaluate指令可用于动态评估VTL。这允许模板评估在渲染时创建的字符串。这样的字符串可用于国际化模板或从数据库中包含模板的一部分。
下面的例子会显示abc
。
#set($ source1 =“abc”) #set($ select =“1”) #set($ dynamicsource =“$ source $ select”) ## $ dynamicsource现在是字符串'$ source1' #evaluate($ dynamicsource)
定义
所述的#define指令使一个VTL的块分配给一个参考。
下面的例子会显示Hello World!
。
#define($ block)Hello $ who#结束 #set($ who ='World!') $块
Velocity宏
该#macro脚本元素允许模板设计者定义VTL模板的重复段。Velocimacros在简单和复杂的各种场景中非常有用。Velocimacro创建的目的仅仅是为了节省击键和最小化印刷错误,提供了Velocimacros概念的介绍。
#macro(d) <tr> <td> </ td> </ tr> #结束
这个例子中定义的Velocimacro是d,它可以以类似于任何其他VTL指令的方式调用:
#D()
当这个模板被调用时,Velocity将用包含单个空数据单元的行代替#d()。如果我们想把某个东西放在那个单元格中,我们可以改变这个宏以允许一个物体:
#macro(d) <tr> <td> $!bodyContent </ td> </ tr> #结束
现在,如果我们以不同的方式调用宏,在名称前面使用#@并为该调用提供一个body和#end,那么当它到达$!bodyContent时,Velocity将渲染body:
#@ d()你好!#结束
您仍然可以调用宏像之前,因为我们使用了无声的参考符号的身体参考($!的BodyContent而不是$的BodyContent),它仍然会呈现一排单,空数据单元格。
一个Velocimacro也可以接受任意数量的参数 – 即使是零参数,如第一个例子所示,它是一个选项 – 但是当Velocimacro被调用时,必须使用与它定义的相同数量的参数来调用。许多Velocimacros比以上定义的更多参与。这是一个Velocimacro,它有两个参数,一个颜色和一个数组。
#macro(tablerows $ color $ somelist) #foreach($ somelist中的$ something) <tr> <td bgcolor = $ color > $ something </ td> </ tr> #结束 #结束
本例中定义的Velocimacro是tablerows,它有两个参数。第一个参数取代$ color,第二个参数取代$ somelist。
任何可以放入VTL模板的东西都可以进入Velocimacro的主体。该tablerows的Velocimacro是的foreach语句。在#tablerows Velocimacro 的定义中有两个#end语句; 第一个属于#foreach,第二个结束Velocimacro定义。
#set($ greatlakes = [“Superior”,“Michigan”,“Huron”,“Erie”,“Ontario”]) #set($ color =“blue”) <表> #tablerows($ color $ greatlakes) </ TABLE>
请注意,$ greatlakes取代$ somelist。当在这种情况下调用#tablerows Velocimacro时,会生成以下输出:
< td bgcolor = “blue” > Superior </ td> </ tr> <tr> <td bgcolor = “blue” > Michigan </ td> </ tr> <tr> <td bgcolor = “blue” > Huron </ td> </ tr> <tr> <td bgcolor = “blue” >伊利</ td> </ tr> <tr> <td bgcolor = “blue” >安大略省</ td> < / tr> </ table>
Velocimacros可以在Velocity模板中内联定义,这意味着它不可用于同一网站上的其他Velocity模板。定义一个Velocimacro,使其可以被所有模板共享,具有明显的优势:它减少了在众多模板上重新定义Velocimacro的需求,节省了工作量并减少了出错的几率,并确保了对宏可用的单个更改一个模板。
如果在Velocimacros模板库中定义#tablerows($ color $ list) Velocimacro,则此宏可用于任何常规模板。它可以多次使用,用于许多不同的目的。在mushroom.vm
致力于所有真菌的模板中,可以调用#tablerowsVelocimacro来列出典型蘑菇的部分:
#set($ parts = [“volva”,“stipe”,“annulus”,“gills”,“pileus”]) #set($ cellbgcol =“#CC00FF”) <表> #tablerows($ cellbgcol $ parts) </ TABLE>
在完成请求时mushroom.vm
,Velocity会在模板库(在文件中定义)中找到#tablerows Velocimacrovelocity.properties
并生成以下输出:
<table> <tr> <td bgcolor = “#CC00FF” > volva </ td> </ tr> <tr> <td bgcolor = “#CC00FF” > stipe </ td> </ tr> <tr> <td bgcolor = “#CC00FF” > annulus </ td> </ tr> <tr> <td bgcolor = “#CC00FF” > gills </ td> </ tr> <tr> <td bgcolor = “#CC00FF” >菌盖</ td> </ tr> </ table>
Velocimacro参数
Velocimacros可以将任何以下VTL元素作为参数:
- 参考:任何以’$’开头的内容
- 字符串文字:类似于“$ foo”或“hello”
- 数字文字:1,2等
- IntegerRange:[1..2]或[$ foo .. $ bar]
- ObjectArray:[“a”,“b”,“c”]
- 布尔值为true
- 布尔值为false
将引用作为参数传递给Velocimacros时,请注意引用是通过“名称”传递的。这意味着它们的价值在Velocimacro内部每次使用时都会“产生”。该功能允许您通过方法调用传递引用,并在每次使用时调用该方法。例如,如图所示调用以下Velocimacro
#macro(callme $ a) $ a $ a $ a #结束 #callme($ foo.bar())
导致引用$ foo的方法bar()被调用3次。
乍看之下,这个功能看起来令人惊讶,但是当您考虑Velocimacros背后的原始动机 – 为了消除常用VTL的重复删除,这很有意义。它允许您执行诸如传递有状态对象之类的事情,例如生成颜色的对象,以重复顺序为着色表行着色到Velocimacro中。
如果您需要绕过此功能,则始终可以将方法中的值作为新的参考并传递:
#set($ myval = $ foo.bar()) #callme($ myval)
Velocimacro属性
velocity.properties
文件中的几行允许灵活实现Velocimacros。请注意,开发者指南中也记录了这些内容。
velocimacro.library
– 所有Velocimacro模板库的逗号分隔列表。默认情况下,Velocity会查找单个库:VM_global_library.vm。配置的模板路径用于查找Velocimacro库。
velocimacro.permissions.allow.inline
– 该属性具有可能的真值或假值,确定是否可以在常规模板中定义Velocimacros。缺省值为true,允许模板设计人员在模板本身中定义Velocimacros。
velocimacro.permissions.allow.inline.to.replace.global
– 对于可能的true或false值,此属性允许用户指定模板中内联定义的Velocimacro是否可以替换全局定义的模板,该模板是通过velocimacro.library
属性在启动时加载的。默认情况下,false
可防止在模板中内联定义的Velocimacros替换在启动时加载的模板库中定义的Velocimacros。
velocimacro.permissions.allow.inline.local.scope
– 此属性的值可能为true或false,默认为false,如果Velocimacros内联定义的内容仅对定义的模板“可见”,则该属性为false。换句话说,通过将此属性设置为true,模板可以定义只能由定义模板使用的内联VM。您可以将其用于花哨的虚拟机技巧 – 如果全局虚拟机调用另一个全局虚拟机和内联范围,则模板可以定义第二个虚拟机的私有实现,该虚拟机将在该模板调用时由第一个虚拟机调用。所有其他模板不受影响。
velocimacro.library.autoreload
– 此属性控制Velocimacro库自动加载。默认值是false
。当设置为true
源Velocimacro库的调用Velocimacro将被检查更改,并在必要时重新加载。这使您可以更改和测试Velocimacro库,而无需重新启动应用程序或servlet容器,就像使用常规模板一样。此模式仅适用于资源加载程序中缓存关闭的情况(例如file.resource.loader.cache = false
)。此功能旨在用于开发,而不是用于生产。
请注意,当两个模板都定义了一个名称相同的宏时,您需要velocimacro.permissions.allow.inline.local.scope
或velocimacro.permissions.allow.inline.to.replace.global
将其设置为true以使每个模板使用其自己的宏版本。
获得文字
VTL使用特殊字符(如$和#)来完成它的工作,所以在模板中使用这些字符时应该加以注意。本部分涉及转义这些字符。
货币
写作“我在农夫的市场上买了一袋4磅的土豆只要2.5美元就没有问题了!” 如前所述,VTL标识符始终以大写或小写字母开头,因此$ 2.50不会被误认为是参考。
转义有效的VTL参考
可能会出现您不希望Velocity提供参考的情况。转义特殊字符是在这些情况下输出VTL特殊字符的最佳方式,当这些特殊字符是有效VTL参考的一部分时,可以使用反斜杠(**)字符来完成。
#set($ email =“foo”) $电子邮件
如果Velocity在您的VTL模板中遇到$ email的引用,它会在上下文中搜索对应的值。这里的输出将是foo,因为定义了$ email。如果未定义$ email,则输出将为$ email。
假设定义了$ email(例如,如果它的值为foo),并且您希望输出$ email。有几种方法可以做到这一点,但最简单的方法是使用转义字符。这是一个演示:
##以下行定义了此模板中的$ email: #set($ email =“foo”) $电子邮件 \ $电子邮件
呈现为
FOO $电子邮件
如果出于某种原因,在上述任何一行之前需要反斜杠,则可以执行以下操作:
##以下行定义了此模板中的$ email: #set($ email =“foo”) \\ $电子邮件 \\\ $电子邮件
呈现为
\ FOO \ $电子邮件
请注意,*字符绑定到左侧的 $ 。从左边的绑定规则导致 \\ $电子邮件呈现为 \ $电子邮件。将这些示例与$ email *未定义的示例进行比较。
$电子邮件 \ $电子邮件 \\ $电子邮件 \\\ $电子邮件
呈现为
$电子邮件 \ $电子邮件 \\ $电子邮件 \\\ $电子邮件
注意Velocity处理的参考定义与那些尚未定义的参考定义不同。这里是一个让一组指令$ foo的值拱起。
#set($ foo =“gibbous”) $ moon = $ foo
输出将是:$ moon = gibbous – 其中$ moon是作为文字输出的,因为它是未定义的,并且输出的是gibbous而不是$ foo。
转义无效的VTL参考
有时候Velocity在遇到一个你从来没有打算成为参考的“无效参考”时,就很难解析你的模板。转义特殊字符也是处理这些情况的最佳方式,但在这些情况下,反斜杠可能会使您失败。而不是简单地试图逃避问题,$
或者#
,你可能应该取而代之:
$ { my :invalid :non :reference }
像这样的东西
#set($ D ='$') $ { D } {my:invalid:non:reference}
当然,您可以将您的字符串$
或#
字符串直接放入Java代码的上下文中(例如context.put("D","$");
)以避免模板中额外的#set()指令。或者,如果你使用的是VelocityTools,你可以像这样使用EscapeTool:
$ { esc 。d } {我:无效:非:参考}
以同样的方式处理有效和无效VTL指令的转义; 这在指令部分有更详细的描述。
转义VTL指令
VTL指令可以用类似于有效VTL引用的方式用反斜杠字符(“\”)转义。
## #include(“a.txt”)呈现为<a.txt>的内容 #include(“a.txt”) ## \ #include(“a.txt”)呈现为#include(“a.txt”) \ #include(“a.txt”) ## \\#include(“a.txt”)呈现为\ <a.txt的内容> \\#include(“a.txt”)
在单个指令中(例如在if-else-end语句中)转义包含多个脚本元素的VTL指令时,应特别小心。这是一个典型的VTL if语句:
#if($ jazz) 维亚切斯拉夫Ganelin #结束
如果$ jazz为true,则输出为
维亚切斯拉夫Ganelin
如果$ jazz为false,则不会输出。转义脚本元素会改变输出。考虑以下情况:
\ #if($ jazz) 维亚切斯拉夫Ganelin \#结束
这会导致指令被转义,但是爵士乐的渲染正常进行。所以,如果$爵士是真的,输出是
#如果属实 ) 维亚切斯拉夫Ganelin #结束
假设反斜杠在合法转义的脚本元素之前:
v \\#if($ jazz) 维亚切斯拉夫Ganelin \\#结束
在这种情况下,如果$ jazz为true,则输出为
\ Vyacheslav Ganelin \
为了理解这一点,请注意,#if( arg )
以换行符结束(返回)的时候将忽略输出中的换行符。因此,#if()
块的主体遵循第一个’\’,由前面的’\’呈现#if()
。最后\与文本不同,因为在’Ganelin’之后有一个换行符,所以最后的\在#end
它之前是该块的主体的一部分。
如果$ jazz为false,则输出为
\
请注意,如果脚本元素未正确转义,事情会开始中断。
\\\#if($ jazz) Vyacheslave Ganelin \\#结束
这里#if被转义了,但是还有一个#end ; 结尾太多会导致解析错误。
VTL:格式化问题
虽然本用户指南中的VTL通常以换行符和空格显示,但VTL如下所示
#set($ imperial = [“Munetaka”,“Koreyasu”,“Hisakira”,“Morikune”]) #foreach($ shogun in $ imperial) $将军 #结束
与Geir Magnusson Jr.发布到Velocity用户邮件列表中的以下代码段一样,可以说明一个完全不相关的问题:
给我发送#设置($ FOO = “$ 10” ,“馅饼” ]) #的foreach ($ 一个 在 $ FOO )$ 一个#结束吧。
Velocity的默认行为是吞噬多余的空白。前面的指令可以写成:
发给我 #set($ foo = [“$ 10 and”,“a pie”]) #foreach($ foo中的$ a) $一个 #结束 请。
或as
发给我 #set($ foo = [“$ 10 and”,“a pie”]) #foreach($ a中的$ foo)$ a #请结束。
在每种情况下,输出将是相同的。请注意,可以将Velocity配置为其他空间吞噬行为。
其他特点和杂记
数学
Velocity拥有一些内置的数学函数,可以在带set指令的模板中使用。以下等式分别是加法,减法,乘法和除法的示例:
#set($ foo = $ bar + 3) #set($ foo = $ bar - 4) #set($ foo = $ bar * 6) #set($ foo = $ bar / 2)
当在两个整数之间执行除法操作时,结果将是一个整数,因为小数部分被丢弃。任何余数都可以通过使用模数(%)运算符获得。
#set($ foo = $ bar%5)
范围运算符
范围运算符可以与#set和#foreach语句一起使用。对于其生成包含整数的对象数组的能力很有用,范围运算符具有以下构造:
[n..m]
既Ñ和米必须是或产生整数。是否米大于或小于ñ都不会有问题; 在这种情况下,范围将简单地倒数。显示如下所示使用范围运算符的示例:
第一个例子: #foreach([1..5]中的$ foo) $ FOO #结束 第二个例子: #foreach([2 ..- 2]中的$ bar) $酒吧 #结束 第三个例子: #set($ arr = [0..1]) #foreach($我在$ arr中) $ I #结束 第四个例子: [1..3]
生成以下输出:
第一个例子: 1 2 3 4 5 第二个例子: 2 1 0 -1 -2 第三个例子: 0 1 第四个例子: [1..3]
请注意,范围运算符仅在与#set和#foreach指令配合使用时才会生成数组,如第四个示例中所示。
有关将表格设置为标准大小的Web页面设计人员,但其中一些人没有足够的数据填充表格时,会发现范围运算符特别有用。
高级问题:逃跑和!
当一个参考文件被沉默!性格和!以*转义字符开头的字符,引用以特殊方式处理。请注意常规转义之间的区别,以及 *之前的特殊情况!遵循它:
#set($ foo =“bar”) $ \!FOO $ \!{} FOO $ \\!foo的 $ \\\!FOO
这呈现为:
$!FOO $!{} FOO $ \!FOO $ \\!foo的
将其与常规转义进行对比,其中*在 $ * 前面:
\ $ FOO \ $!FOO \ $!{} FOO \\ $!{} FOO
这呈现为:
$ FOO $!FOO $!{} FOO \酒吧
Velocimacro杂记
本节是关于Velocimacros相关主题的迷你常见问题解答。本部分将随着时间而改变,因此值得不时检查新信息。
注意:在本节中,’Velocimacro’通常缩写为’VM’。
我可以使用指令或其他VM作为VM的参数吗?
示例: #center( #bold("hello") )
不。指令不是指令的有效参数,对于大多数实际用途,虚拟机是指令。
但是,有些事情你可以做。一个简单的解决方案就是利用’doublequote’(“)来呈现它的内容这一事实。
#set($ stuff =“#bold('hello')”) #center($ stuff)
你可以保存一个步骤…
#center(“#bold('hello')”)
请注意,在后面的例子中,arg是在虚拟机内部进行评估的,而不是在调用级别。换句话说,虚拟机的参数被全部传入并在它传入的虚拟机中进行评估。这可以让你做这样的事情:
#macro(内部$ foo) inner:$ foo #结束 #macro(outer $ foo) #set($ bar =“outerlala”) outer:$ foo #结束 #set($ bar ='calltimelala') #outer(“#inner($ bar)”)
输出在哪里
外 : 内 : 外拉拉
因为“#inner($ bar)”的评估发生在#outer()内部,所以在#outer()中设置的$ bar值就是使用的值。
这是一个有意和嫉妒的守护功能 – 参数通过’名字’传递给虚拟机,所以你可以把虚拟机的东西像有状态的引用
#macro(foo $ color) <tr bgcolor = $ color > <td> Hi </ td> </ tr> <tr bgcolor = $ color > <td> There </ td> </ tr> #结束 #foo($ bar.rowColor())
并重复调用rowColor(),而不是只调用一次。为了避免这种情况,请调用VM外部的方法,并将值传递给VM。
#set($ color = $ bar.rowColor()) #foo($ color)
我可以通过#parse()注册Velocimacros吗?
是! 在Velocity 1.6中这成为可能。
如果您使用的是早期版本,您的Velocimacros必须在模板中首次使用之前进行定义。这意味着你的#macro()声明应该在使用Velocimacros之前出现。
如果您尝试#parse()包含内联#macro()指令的模板,这一点很重要。由于#parse()在运行时发生,并且解析器决定模板中的VM外观元素是否为parsetime上的VM,因此#parse() – 一组虚拟机声明将无法按预期工作。为了解决这个问题,只需使用该velocimacro.library
工具在启动时使Velocity加载虚拟机。
什么是Velocimacro Autoreloading?
有一个属性,意在用于开发,而不是生产:
`velocimacro.library.autoreload`
默认为false。当设置为true 时
`<type> .resource.loader.cache = false`
(哪里 是你正在使用的资源加载器的名称,比如’file’),那么Velocity引擎会自动重新加载对你的Velocimacro库文件的修改,所以你不必转储servlet引擎(或应用程序)或者做其他技巧让您的Velocimacros重新加载。
这是一组简单的配置属性。
file.resource.loader.path =模板 file.resource.loader.cache = false velocimacro.library.autoreload = true
不要把它放在生产中。
字符串串联
开发人员问的一个常见问题是如何进行字符串连接?Java中有没有类似于’+’的运算符?。
要在VTL中进行引用的连接,您只需将它们放在一起即可。你想把它们放在一起的环境很重要,所以我们将用一些例子来说明。
在模板的常规’schmoo’中(当您将其与常规内容混合时):
#set($ size =“Big”) #set($ name =“Ben”) 时钟是$ size $ name。
并且输出将呈现为’时钟是BigBen’。对于更有意思的情况,比如当你想连接字符串以传递给方法,或者设置一个新的引用时,只需要
#set($ size =“Big”) #set($ name =“Ben”) #set($ clock =“$ size $ name”) 时钟是$时钟。
这将导致相同的输出。作为最后一个例子,当你想将’static’字符串与你的引用混合时,你可能需要使用’正式引用’:
#set($ size =“Big”) #set($ name =“Ben”) #set($ clock =“ $ { size } Tall $ name ”) 时钟是$时钟。
现在输出是’时钟是BigTallBen’。正式表示法是必要的,所以解析器知道你的意思是使用引用’$ size’和’$ sizeTall’,如果'{}’不在那里,就会这样做。
反馈
如果您在本手册中遇到任何错误或有其他与Velocity用户指南有关的反馈,请发送电子邮件到Velocity开发人员名单。谢谢!