简要
References begin with $ and are used to get something.
Directives begin with # and are used to do something.
注释 单行 ## 多行 #* *# doc #** *#
引用
变量
属性
注意$customer.Address可以表示customer的getAddress方法,也可以表示customer map中的Address对应的value.
方法
As of Velocity 1.6, all array references are now "magically" treated as if they are fixed-length lists. This means that you can call java.util.List methods on array references.
可变参数当作数组。
属性查找顺序
小写的属性$customer.address
1.getaddress()
2.getAddress()
3.get("address")
4.isAddress()
大写的属性$customer.Address
1.getAddress()
2.getaddress()
3.get("Address")
4.isAddress()
Rendering
引擎把每一个引用都转变为String,可以调用toString方法转变。
Formal Reference Notation
Jack is a ${vice}maniac.
Now Velocity knows that $vice, not $vicemaniac, is the reference. Formal notation is often useful when references are directly adjacent to text in a template.
Quiet Reference Notation
- <input?type="text"?name="email"?value="$email"/>??
<input type="text" name="email" value="$email"/>
当$email没有定义的时候输出$email.
- <input?type="text"?name="email"?value="$!email"/>??
<input type="text" name="email" value="$!email"/>
当$email没有定义的时候输出"".
Strict References Setting
对未定义变量,或null变量调用方法抛异常。
但是if语句可以使用未定义变量。
Directives
#set
- #set(?$monkey.Say?=?["Not",?$my,?"fault"]?)?##?ArrayList ??
- #set(?$monkey.Map?=?{"banana"?:?"good",?"roast?beef"?:?"bad"})?##?Map??
#set( $monkey.Say = ["Not", $my, "fault"] ) ## ArrayList #set( $monkey.Map = {"banana" : "good", "roast beef" : "bad"}) ## Map
For the ArrayList example the elements defined with the [..] operator are accessible using the methods defined in the ArrayList class. So, for example, you could access the first element above using $monkey.Say.get(0).
Similarly, for the Map example, the elements defined within the { } operator are accessible using the methods defined in the Map class. So, for example, you could access the first element above using $monkey.Map.get("banana") to return a String 'good', or even $monkey.Map.banana to return the same value.
这个比较容易迷惑人。
If the RHS is a property or method reference that evaluates to null, it will not be assigned to the LHS.
- #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??
#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
If $query.criteria("name") returns the string "bill", and $query.criteria("address") returns null, the above VTL will render as the following:
- The?result?of?the?first?query?is?bill ??
- The?result?of?the?second?query?is?bill??
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??
#set( $criteria = ["name", "address"] ) #foreach( $criterion in $criteria ) #set( $result = $query.criteria($criterion) ) #if( $result ) Query was successful #end #end
In the above example, it would not be wise to rely on the evaluation of $result to determine if a query was successful. After $result has been #set (added to the context), it cannot be set back to null (removed from the context).
One solution to this would be to pre-set $result to false. Then if the $query.criteria() call fails, you can check.
- #set(?$criteria?=?["name",?"address"]?) ??
- #foreach(?$criterion?in?$criteria?) ??
- ????#set(?$result?=?false?) ??
- ????#set(?$result?=?$query.criteria($criterion)?) ??
- ????#if(?$result?) ??
- ????????Query?was?successful ??
- ????#end ??
- #end??
#set( $criteria = ["name", "address"] ) #foreach( $criterion in $criteria ) #set( $result = false ) #set( $result = $query.criteria($criterion) ) #if( $result ) Query was successful #end #end
Literals
''和""的区别 ""可以"hello $name".
- #literal() ??
- #end??
#literal() #end
Alternately, the #literal script element allows the template designer to easily use large chunks of uninterpreted content in VTL code. This can be especially useful in place of escaping multiple directives.
Conditionals
If / ElseIf / Else
if测试(1)布尔值(2)引用是否为空
Relational and Logical Operators
Note that the semantics of == are slightly different than Java where == can only be used to test object equality. In Velocity the equivalent operator can be used to directly compare numbers, strings, or objects. When the objects are of different classes, the string representations are obtained by calling toString() for each object and then compared.
Foreach Loop
可以得到$velocityCount,$velocityHasNext。
变量名,起始下标都可以在配置文件里面更改。
还可以设置directive.foreach.maxloops。
在foreach中可以#break。
Include
The #include script element allows the template designer to import a local file, which is then inserted into the location where the #include directive is defined. The contents of the file are not rendered through the template engine. For security reasons, the file to be included may only be under TEMPLATE_ROOT.
Parse
The #parse script element allows the template designer to import a local file that contains VTL. Velocity will parse the VTL and render the template specified.
可以设置directive.parse.max.depth,默认是10.
允许递归。
Stop
The #stop script element prevents any further text or references in the page from being rendered. This is useful for debugging purposes.
Evaluate
The #evaluate directive can be used to dynamically evaluate VTL.
Define
The #define directive lets one assign a block of VTL to a reference.
Velocimacros
宏的参数和调用时的个数必须匹配。
宏有inline的宏,对其他模板不可见。
宏传递的是名字,注意宏执行的时间。
Velocimacro Properties
velocimacro.library
velocimacro.permissions.allow.inline
velocimacro.permissions.allow.inline.to.replace.global
velocimacro.permissions.allow.inline.local.scope
velocimacro.context.localscope
velocimacro.library.autoreload
Getting literal
有效velocity变量的转义
转义字符\
注意velocity对未定义变量和已定义变量的处理是不一样的。
无效velocity变量的转义
${my:invalid:non:reference}
改成
#set( $D = '$' )
${D}{my:invalid:non:reference}
Escaping VTL Directives
这个转义时要比较小心。
Other Features and Miscellany
Math 加减乘除 mod
Range Operator 设置数组和foreach.
Advanced Issues: Escaping and !
Can I use a directive or another VM as an argument to a VM?
No. A directive isn't a valid argument to a directive, and for most practical purposes, a VM is a directive.
但是可以#center( "#bold( 'hello' )" )
Can I register Velocimacros via #parse() ?
Yes! This became possible in Velocity 1.6.
This is important to remember if you try to #parse() a template containing inline #macro() directives. Because the #parse() happens at runtime, and the parser decides if a VM-looking element in the template is a VM at parsetime, #parse()-ing a set of VM declarations won't work as expected. To get around this, simply use the velocimacro.library facility to have Velocity load your VMs at startup.
对于宏定义的查找是在parsetime,所以runtime的parse中如果有宏会有问题。
What is Velocimacro Autoreloading?
宏自动加载,用于开发环境。
字符串连接
放在一起就好。