ï»??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲日本一区二区三区在线,欧美区一区二区三区,91精品国产综合久久福利http://www.aygfsteel.com/caizh2009/category/45999.html与大家共同成é•?/description>zh-cnFri, 20 Aug 2010 10:00:06 GMTFri, 20 Aug 2010 10:00:06 GMT60Velocity模板(VM)语言介绍http://www.aygfsteel.com/caizh2009/archive/2010/08/20/329495.htmlž®èœæ¯›æ¯›ž®èœæ¯›æ¯›Fri, 20 Aug 2010 09:57:00 GMThttp://www.aygfsteel.com/caizh2009/archive/2010/08/20/329495.htmlhttp://www.aygfsteel.com/caizh2009/comments/329495.htmlhttp://www.aygfsteel.com/caizh2009/archive/2010/08/20/329495.html#Feedback0http://www.aygfsteel.com/caizh2009/comments/commentRss/329495.htmlhttp://www.aygfsteel.com/caizh2009/services/trackbacks/329495.html Velocity是一个基于java的模板引擎(template engineåQ‰ã€‚它允许ä»ÖM½•äºÞZ»…仅简单的使用模板语言åQˆtemplate languageåQ‰æ¥å¼•用由java代码定义的对象ã€?
当Velocity应用于web开发时åQŒç•Œé¢è®¾è®¡äh员可以和java½E‹åºå¼€å‘äh员同步开发一个遵循MVC架构的web站点åQŒä¹Ÿž®±æ˜¯è¯ß_¼Œ™åµé¢è®¾è®¡äº? 员可以只å…Ïx³¨™åµé¢çš„æ˜¾½Cºæ•ˆæžœï¼Œè€Œç”±java½E‹åºå¼€å‘äh员关注业务逻辑¾~–码。Velocityž®†java代码从web™åµé¢ä¸­åˆ†¼›Õd‡ºæ¥ï¼Œ˜q™æ ·ä¸ºweb站点的长 期维护提供了便利åQŒåŒæ—¶ä¹Ÿä¸ºæˆ‘们在JSPå’ŒPHP之外又提供了一¿Uå¯é€‰çš„æ–ÒŽ¡ˆã€?
Velocity的能力远不止web站点开发这个领域,例如åQŒå®ƒå¯ä»¥ä»Žæ¨¡æ¿ï¼ˆtemplateåQ‰äñ”生SQLå’ŒPostScript、XMLåQŒå®ƒä¹? 可以被当作一个独立工å…äh¥äº§ç”Ÿæºä»£ç å’ŒæŠ¥å‘ŠåQŒæˆ–者作为其他系¾lŸçš„集成¾l„äšg使用。Velocityä¹Ÿå¯ä»¥äØ“Turbine web开发架构提供模板服务(template serviceåQ‰ã€‚Velocity+Turbine提供一个模板服务的方式允许一个web应用以一个真正的MVC模型˜q›è¡Œå¼€å‘ã€?

Velocityèƒ½äØ“æˆ‘ä»¬ä½œä»€ä¹ˆï¼Ÿ
The Mud Store Example
假设你是一家专门出售Mud的在¾U¿å•†åº—çš„™åµé¢è®¾è®¡äººå‘˜åQŒè®©æˆ‘们暂且¿U°å®ƒä¸?#8220;在线MUD商店”。你们的业务很旺åQŒå®¢æˆ·ä¸‹äº†å„¿Uç±»åž‹å’Œæ•°é‡çš„mudè®? 单。他们都是通过输入用户名和密码后才登陆åˆîC½ çš„网站,登陆后就允许他们查看订单òq¶è´­ä¹°æ›´å¤šçš„mud。现在,一¿Uéžå¸¸æµè¡Œçš„mud正在打折销售。另外有一 些客戯‚§„律性的购买另外一¿Uä¹Ÿåœ¨æ‰“折但是不是很‹¹è¡Œçš„Bright Red MudåQŒç”±äºŽè´­ä¹°çš„äººåÆˆä¸å¤šæ‰€ä»¥å®ƒè¢«å®‰¾|®åœ¨™åµé¢çš„è¾¹¾~˜ã€‚所有用æˆïLš„信息都是被跟ítªåƈ存放于数据库中的åQŒæ‰€ä»¥æŸå¤©æœ‰ä¸€ä¸ªé—®é¢˜å¯èƒ½ä¼šå†’出来:ä¸ÞZ»€ä¹ˆä¸ä½¿ç”¨ velocity来ä‹É用户更好的浏览他们感兴趣的商品呢åQ?
Velocity使得web™åµé¢çš„客户化工作非常å®ÒŽ˜“。作ä¸ÞZ¸€ä¸ªweb site的设计äh员,你希望每个用æˆïL™»é™†æ—¶éƒ½æ‹¥æœ‰è‡ªå·Þqš„™åµé¢ã€?
你会见了一些公司内的èÊYä»¶å·¥½E‹å¸ˆåQŒä½ å‘现他们每个人都同意客户应该拥有å…ähœ‰ä¸ªæ€§åŒ–的信息。那让我们把软äšg工程师应该作的事情发在一边,看一看你应该作些什么吧ã€?
你可能在™åµé¢å†…嵌套如下的VTL声明åQ?
<html>
<body>
Hello $customer.Name!
<table>
#foreach( $mud in $nudsOnSpecial )
#if ( $customer.hasPurchased( $mud ) )
<tr><td>$flogger.getPromo( $mud )</td></tr>
#end
#end
</table>

Velocity Template Language(VTL):AN introduction
VTL意味着提供最½Ž€å•、最å®ÒŽ˜“òq¶ä¸”最整洁的方式合òq‰™¡µé¢åŠ¨æ€å†…å®V€?
VTL使用references来在web site内嵌套动态内容,一个变量就是一¿Uç±»åž‹çš„reference。变量是某种¾cÕdž‹çš„refreenceåQŒå®ƒå¯ä»¥æŒ‡å‘java代码中的定义åQŒæˆ–者从当前 ™åµé¢å†…定义的VTL statement得到倹{€‚下面是一个VTL statement的例子,它可以被嵌套到HTML代码中:
  #set ( $a = “Velocity” )
和所有的VTL statementä¸€æ øP¼Œ˜q™ä¸ªstatementä»¥ï¼ƒå­—ç¬¦å¼€å§‹åÆˆä¸”åŒ…å«ä¸€ä¸ªdirectiveåQšset。当一个在¾U¿ç”¨æˆ¯‚¯·æ±‚你的页面时åQŒVelocity Templating Enginež®†æŸ¥è¯¢æ•´ä¸ªé¡µé¢ä»¥ä¾¿å‘现所有#字符åQŒç„¶åŽç¡®å®šå“ªäº›æ˜¯VTL statementåQŒå“ªäº›ä¸éœ€è¦VTL作ä“Q何事情ã€?
åQƒå­—½W¦åŽç´§è·Ÿä¸€ä¸ªdirectiveåQšsetæ—Óž¼Œ˜q™ä¸ªset directive使用一个表辑ּåQˆä‹É用括号封闭)――一个方½E‹å¼åˆ†é…ä¸€ä¸ªå€¼ç»™å˜é‡ã€‚变量被列在左边åQŒè€Œå®ƒçš„倯D¢«åˆ—在双™¾¹åQŒæœ€åŽä»–们之间ä‹É用=号分剌Ӏ?
在上面的例子中,变量æ˜?aåQŒè€Œå®ƒçš„值是Velocity。和其他的references一样以$字符开始,而值æ€ÀL˜¯ä»¥åŒå¼•号ž®é—­ã€‚Velocity中仅有String可以被赋值给变量ã€?
è®îC½ä»¥ä¸‹çš„规则:
使用$字符开始的references用于得到什么;使用#字符开始的directives用于作些什么�
Hello Velocity World!
一旦某个变量被分配了一个å€û|¼Œé‚£ä¹ˆä½ å°±å¯ä»¥åœ¨HTMLæ–‡äšgçš„ä“Q何地方引用它。在下面的例子中åQŒä¸€ä¸ªå€ÆD¢«åˆ†é…¾l?foo变量åQŒåƈ在其后被引用ã€?
<html>
<body>
#set ( $foo = “Velocity” )
Hello $foo World!
</body>
</html>
上面的实现结果是在页面上打印“Hello Velocity WorldåQ?#8221;
ä¸ÞZº†ä½¿åŒ…含VTL directivesçš„statement更具有可è¯ÀL€§ï¼Œæˆ‘们鼓励你在新行开始每个VTL statementåQŒå°½½Ž¡ä½ ä¸æ˜¯å¿…é¡»˜q™ä¹ˆä½œã€‚Set directivež®†åœ¨åŽé¢è¯¦ç»†æè¿°ã€?
注释
单行注释åQ?
  ## This is a single line comment.
多行注释åQ?
  #*
   Thus begins a multi-line comment. Online visitors won’t
   see this text because the Velocity Templating Engine will
ignore it.
  *#
文档格式åQ?
  #**
   This is a VTL comment block and
   may be used to store such information
as the document author and versioning
   information:
   @version 5
   @author
  *#

References
在VTL中有三种¾cÕdž‹çš„referencesåQšå˜é‡?variables)、属æ€?properties)、方æ³?methods)。作ä¸ÞZ¸€ä¸ªä‹É 用VTL的页面设计者,你和你的工程师必™åÕd°±references的名¿U°è¾¾æˆå…±è¯†ï¼Œä»¥ä¾¿ä½ å¯ä»¥åœ¨ä½ çš„template中ä‹É用它们ã€?
Everything coming to and from a reference被作ä¸ÞZ¸€ä¸ªString对象处理。如果有一个对è±?foo是一个Integer对象åQŒé‚£ä¹ˆVelocityž®†è°ƒç”¨å®ƒçš„toString()æ–ÒŽ³•ž®†è¿™ä¸ªå¯¹è±¡è{åž‹äØ“String¾cÕdž‹ã€?
  变量
  格式要求同javaã€?
  属æ€?
  例子åQ?
    $customer.Address
    $purchase.Total
$customer.Address有两¿Uå«ä¹‰ã€‚它可以表示åQšæŸ¥æ‰¾hashtable对象customer中以Address为关键字的å€û|¼›ä¹Ÿå¯ 以表½Cø™°ƒç”¨customer对象的getAddress()æ–ÒŽ³•。当你的™åµé¢è¢«è¯·æ±‚æ—¶åQŒVelocityž®†ç¡®å®šä»¥ä¸Šä¸¤¿Uæ–¹å¼é€‰ç”¨é‚£ç§åQŒç„¶åŽè¿”回适当的倹{€?
æ–ÒŽ³•
一个方法就是被定义在java中的一ŒDµä»£ç ï¼Œòq¶ä¸”它有完成某些有用工作的能力,例如一个执行计½Ž—和判断条äšg是否成立、满­‘³ç­‰ã€‚方法是一个由$å¼€å§‹åÆˆè·ŸéšVTL标识½W¦ç»„成的ReferencesåQŒä¸€èˆ¬è¿˜åŒ…括一个VTLæ–ÒŽ³•体。例如:
  $customer.getAddress()
  $purchase.getTotal()
  $page.setTitle( “My Home Page” )
  $person.setAttributes( [“Strange”, “Weird”, “Excited”] )
前两个例å­?customer.getAddress()å’?purchase.getTotal()看è“v来挺想上面的属æ€?customer.Address å’?$purchase.Total。如果你觉得他们之间有某¿Uè”¾pȝš„话,那你是正¼‹®çš„ã€?
VTL属性可以作为VTLæ–ÒŽ³•的羃写ã€?customer.Address属性和使用$customer.getAddress()æ–ÒŽ³•å…ähœ‰ç›¸åŒçš„æ•ˆæžœã€‚如果可能的话ä‹É用属性的方式是比较合理的。属性和æ–ÒŽ³•的不同点在于你能够给一个方法指定一个参数列表ã€?
正式reference标记
reference的正是格式如下:
  ${mudSlinger}        变量
  ${customer.Address}    属æ€?
  ${purchase.getTotal()}    æ–ÒŽ³•
非正是格式更见常用,但是有时˜q˜æ˜¯ä½¿ç”¨æ­£æ˜¯æ ¼å¼æ¯”较适合。例如:你希望通过一个变é‡?vice来动态的¾l„织一个字½W¦ä¸²ã€?
  Jack is a $vicemaniac.
本来变量æ˜?vice现在却变成了$vicemaniacåQŒè¿™æ ·Veloctiyž®×ƒ¸çŸ¥é“您到底要什么了。所以,应该使用正是格式书写
  Jack is a ${vice}maniac
现在Velocity知道变量�vice而不�vicemaniac�
Quiet reference notation
例如åQ?
  <input type=”text” name=”email” value=”$email” />
当页面的form被初始加载时åQŒå˜é‡?email˜q˜æ²¡æœ‰å€û|¼Œ˜q™æ—¶ä½ è‚¯å®šæ˜¯å¸Œæœ›å®ƒèƒ½å¤Ÿæ˜¾½CÞZ¸€ä¸ªblank text来代替输å‡?#8221;$email”˜q™æ ·çš„å­—ŒDüc€‚那么ä‹É用quiet reference notationž®±æ¯”较合适ã€?
  <input type=”text” name=”email” value=”$!email”/>
˜q™æ ·æ–‡æœ¬æ¡†çš„初始值就不会是email而是½Iºå€égº†ã€?
正式和quiet格式的reference notation也可一同ä‹Éç”¨ï¼Œåƒä¸‹é¢è¿™æ øP¼š
  <input type=”text” name=”email” value=”$!{email}”/>
Getting literal
Velocity使用ç‰ÒŽ®Šå­—符$å’?来帮助它工作åQŒæ‰€ä»¥å¦‚果要在template里ä‹É用这些特ŒDŠå­—½W¦è¦æ ¼å¤–ž®å¿ƒã€‚本节将讨论$字符ã€?
  货币字符
在VTL中ä‹Éç”?2.5˜q™æ ·çš„货币标识是没有问题得的åQŒVTL不会ž®†å®ƒé”™è®¤ä¸ºæ˜¯ä¸€ä¸ªreferenceåQŒå› ä¸ºVTL中的referenceæ€ÀL˜¯ä»¥ä¸€ä¸ªå¤§å†™æˆ–者小写的字母开始ã€?
Escaping valid VTL reference
VTL中ä‹Éç”?#8220;"”ä½œäØ“é€ƒé€¸ç¬¦ã€?
例如åQ?
  #set( $email = “foo” )
  $email
  "$email
  ""$email
  """$email
ž®†render为:
  foo
  $email
  "foo
  ""$email
如果email变量没有被定义则
  $email
  "$email
  ""$email
  """$email
ž®†è¢«render为:
  $email
  "$email
  ""$email
  """$email
注意åQšVTL中未被定义的变量ž®†è¢«è®¤äؓ是一个字½W¦ä¸²åQŒæ‰€ä»¥ä»¥ä¸‹ä¾‹å­ï¼š
  #set( $foo = “gibbous” )
  $moon = $foo
的输出结果是åQ?
$moon = gibbous
Case substitution
现在你已¾lå¯¹reference比较熟悉了,你可以将他们高效的应用于你的template了。Velocity利用了很多java规范以方便了设计人员的ä‹É用。例如:
  $foo
  $foo.getBar()
  ## is the same as
  $foo.Bar

  $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}
但是åQŒæ³¨æ„VTL中不会将reference解释为对象的实例变量。例如:$foo.Namež®†è¢«è§£é‡Šä¸ºFoo对象的getNameåQˆï¼‰æ–ÒŽ³•åQŒè€Œä¸æ˜¯Foo对象的Name实例变量ã€?
Directives
Reference允许设计者ä‹É用动态的内容åQŒè€Œdirective使得你可以应用java代码来控制你的显½Cºé€»è¾‘åQŒä»Žè€Œè¾¾åˆîC½ æ‰€æœŸæœ›çš„æ˜¾½Cºæ•ˆæžœã€?
  #set
  #set directive被用于设¾|®ä¸€ä¸ªreference的倹{€‚例如:
    #set ( $primate = “monkey” )
    #set ( $customer.Behavior = $primate )
赋值左侧的åQˆLHSåQ‰å¿…™åÀL˜¯ä¸€ä¸ªå˜é‡æˆ–者属性reference。右侧(RHSåQ‰å¯ä»¥æ˜¯ä»¥ä¸‹¾cÕdž‹ä¸­ä¸€¿Uï¼š
l  变量reference
l  String literal
l  属性reference
l  æ–ÒŽ³•reference
l  number literal
l  ArrayList
下面是应用各¿Uç±»åž‹çš„RHS的例子:
  åQƒset ( $monkey = $bill ) ##变量reference
  åQƒset ( $monkey.Friend = “monica” ) ##String literal
  åQƒset ( $monkey.Blame = $whitehouse.Leak )##属性reference
  åQƒset ( $monkey.Plan = $spindoctor.weave($web) )##æ–ÒŽ³•reference
  åQƒset ( $monkey.Number = 123 )##Number literal
  åQƒset ( $monkey.Say = [“Not”, $my, “fault”] )##ArrayList
注意åQšæœ€åŽä¸€ä¸ªä¾‹å­çš„å–å€¼æ–¹æ³•äØ“åQ?monkey.Say.get(0)
RHS也可以是一个简单的½Ž—术表达式:
  #set ( $value = $foo + 1 )
  #set ( $value = $bar -1 )
#set ( $value = $foo * $bar )
#set ( $value = $foo / $bar )
如果你的RHS是一个nullåQŒVTL的处理将比较ç‰ÒŽ®ŠåQšå®ƒž®†æŒ‡å‘一个已¾lå­˜åœ¨çš„referenceåQŒè¿™å¯¹åˆå­¦è€…来讲可能是比较费解的。例如:
  #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”)˜q”回一ä¸?#8220;bill”åQŒè€?query.criteria(“address”)˜q”回的是nullåQŒåˆ™æ˜„¡¤ºçš„结果如下:
  The result of the first query is bill
  The result of the first query is bill
看看下面的例子:
  #set( $criteria = ["name", "address"] )
#foreach( $criterion in $criteria )
#set( $result = $query.criteria($criterion) )
  #if( $result )
  Query was successful
     #end
#end
在上面的例子中,½E‹åºž®†ä¸èƒ½æ™ºèƒ½çš„æ ÒŽ®$result的值决定查询是否成功。在$resultè¢?set后(added to the contextåQ‰ï¼Œå®ƒä¸èƒ½è¢«è®„¡½®å›žnullåQˆremoved from the contextåQ‰ã€‚打印的¾l“æžœž®†æ˜¾½CÞZ¸¤‹Æ¡æŸ¥è¯¢ç»“果都成功了,但是实际上有一个查询是å¤ÞpÓ|çš„ã€?
ä¸ÞZº†è§£å†³ä»¥ä¸Šé—®é¢˜æˆ‘们可以通过预先定义的方式:
  #set( $criteria = [“name”, “address”] )
  #foreach( $criterion in $criteria )
    #set( $result = false )
    #set( $result = $query.criteria( $criterion ) )
    #if( $result )
      Query was successful
    #end
  #end
  String Literals
  当你使用#set directiveåQŒString literalž®é—­åœ¨ä¸€å¯¹åŒå¼•号内ã€?
    #set ( $directoryRoot = “www” )
    #set ( $templateName = “index.vm” )
    #set ( $template = “$directoryRoot/$tempateName” )
    $template
  上面˜q™æ®µä»£ç çš„è¾“å‡ºç»“æžœäØ“åQšwww/index.vm
  但是åQŒå½“string literal被封装在单引号内æ—Óž¼Œå®ƒå°†ä¸è¢«è§£æžåQ?
    #set ( $foo = “bar” )
    $foo
    #set ( $blargh = ‘$foo’ )
  ¾l“æžœåQ?
    bar
    $foo
  上面˜q™ä¸ªç‰ÒŽ€§å¯ä»¥é€šè¿‡ä¿®æ”¹velocity.propertiesæ–‡äšgçš„stringliterals.interpolate = false的值来改变上面的特性是否有效ã€?
条äšg语句
  if/elseif/else
当一个web™åµé¢è¢«ç”Ÿæˆæ—¶ä½¿ç”¨Velocityçš?if directriveåQŒå¦‚果条件成立的话可以在™åµé¢å†…嵌入文字。例如:
  #if ( $foo )
    <strong>Velocity!</strong>
  #end
上例中的条äšg语句ž®†åœ¨ä»¥ä¸‹ä¸¤ç§æ¡äšg下成立:
l  $foo是一个boolean型的变量åQŒä¸”它的å€égØ“true
l  $foo变量的å€ég¸ä¸ºnull
˜q™é‡Œéœ€è¦æ³¨æ„ä¸€ç‚¹ï¼šVelocity context仅仅能够包含对象åQŒæ‰€ä»¥å½“我们è¯?#8220;boolean”时实际上代表的时一个Boolean对象。即便某个方法返回的是一个booleanå€û|¼ŒVelocity也会利用内省机制ž®†å®ƒè½¬æ¢ä¸ÞZ¸€ä¸ªBoolean的相同倹{€?
如果条äšg成立åQŒé‚£ä¹?ifå’?end之间的内容将被显½Cºã€?
#elseifå’?else元素可以å?if一同ä‹É用。例如:
  #if( $foo < 10 )
    <strong> Go North </strong>
  #elseif( $foo == 10 )
    <strong> Go East </strong>
  #elseif( $foo == 6 )
    <strong> Go South </strong>
  #else
    <strong> Go West </strong>
  #end
注意˜q™é‡Œçš„Velocityçš„æ•°å­—æ˜¯ä½œäØ“Integer来比较的――其他类型的对象ž®†ä‹Éå¾—æ¡ä»¶äØ“falseåQŒä½†æ˜¯ä¸Žjava不同它ä‹Éç”?#8220;åQï¼”来比较两个å€û|¼Œè€Œä¸”velocity要求½{‰å·ä¸¤è¾¹çš„值类型相同ã€?
关系、逻辑˜qç®—½W?
Velocity中ä‹É用等åäh“ä½œç¬¦åˆ¤æ–­ä¸¤ä¸ªå˜é‡çš„å…³¾p…R€‚例如:
#set ( $foo = “deoxyribonucleic acid” )
#set ( $bar = “ribonucleic acid” )
#if ( $foo == $foo )
  In this case it’s clear they aren’t equivalent.So…
#else
  They are not equivalent and this will be the output.
#end

Velocity有AND、ORå’ŒNOT逻辑˜qç®—½W¦ã€‚下面是一些例子:
  ## logical AND
  #if( $foo && $bar )
    <strong> This AND that </strong>
  #end

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

  ##logical NOT
  #if ( !$foo )
    <strong> NOT that </strong>
  #end
循环
  Foreach循环
  例子åQ?
    <ul>
      #foreach ( $product in $allProducts )
        <li> $product </li>
      #end
    </ul>
  每次循环$allProducts中的一个值都会赋¾l?product变量ã€?
$allProducts可以是一个Vector、Hashtable或者Array。分配给$product的值是一个java对象åQŒåƈ且可ä»? 通过变量被引用。例如:如果$product是一个javaçš„Product¾c»ï¼Œòq¶ä¸”˜q™ä¸ªäº§å“çš„名字可以通过调用他的getNameåQˆï¼‰æ–ÒŽ³•得到ã€?
现在我们假设$allProducts是一个HashtableåQŒå¦‚果你希望得到它的keyåº”è¯¥åƒä¸‹é¢è¿™æ øP¼š
<ul>
#foreach ( $key in $allProducts.keySet() )
<li>Key: $key -> Value: $allProducts.get($key) </li>
#end
</ul>

Velocity˜q˜ç‰¹åˆ«æä¾›äº†å¾—到循环‹Æ¡æ•°çš„æ–¹æ³•,以便你可以像下面˜q™æ ·ä½œï¼š
<table>
#foreach ( $customer in $customerList )
<tr><td>$velocityCount</td><td>$customer.Name</td></tr>
#end
</table>
$velocityCount变量的名字是Velocity默认的名字,你也可以通过修改velocity.propertiesæ–‡äšg来改变它ã€? 默认情况下,计数ä»?#8220;1”开始,但是你可以在velocity.properties讄¡½®å®ƒæ˜¯ä»?#8220;1”˜q˜æ˜¯ä»?#8220;0”开始。下面就是文件中的配¾|®ï¼š
  # Default name of loop counter
  # variable reference
  directive.foreach.counter.name = velocityCount

  # Default starting value of the loop
  # counter variable reference
  directive.foreach.counter.initial.value = 1

include
#include script element允许模板设计者引入本地文件。被引入文äšg的内容将不会通过模板引擎被renderã€‚äØ“äº†å®‰å…¨çš„åŽŸå› åQŒè¢«å¼•入的本地文件只能在TEMPLATE_ROOT目录下ã€?
  #inclued ( “one.txt” )
如果您需要引入多个文ä»Óž¼Œå¯ä»¥ç”¨é€—号分隔ž®Þp¡ŒåQ?
  #include ( “one.gif”, “two.txt”, “three.htm” )
在括号内可以是文件名åQŒä½†æ˜¯æ›´å¤šçš„æ—¶å€™æ˜¯ä½¿ç”¨å˜é‡çš„:
  #inclue ( “greetings.txt”, $seasonalstock )

parse
#parse script element允许模板设计者一个包含VTL的本地文件。Velocityž®†è§£æžå…¶ä¸­çš„VTLòq¶render模板ã€?
  #parse( “me.vm” )
ž®±åƒ#includeåQ?parse接受一个变量而不是一个模æÑ€‚ä“Q何由#parse指向的模杉Kƒ½å¿…须包含在TEMPLATE_ROOT目录下。与#include不同的是åQ?parse只能指定单个对象ã€?
你可以通过修改velocity.propertiesæ–‡äšgçš„parse_direcive.maxdepth的值来控制一个template可以包含的最å¤?parse的个数――默认值是10ã€?parse是可以递归调用的,例如åQšå¦‚æžœdofoo.vm包含如下行:
  Count down.
  #set ( $count = 8 )
  #parse ( “parsefoo.vm” )
  All done with dofoo.vm!
那么在parsefoo.vm模板中,你可以包含如下VTLåQ?
  $count
  #set ( $count = $count – 1 )
  #if ( $count > 0 )
    #parse( “parsefoo.vm” )
  #else
    All done with parsefoo.vm!
  #end
的显½Cºç»“æžœäØ“åQ?
  Count down.
  8
  7
  6
  5
  4
  3
  2
  1
  0
  All done with parsefoo.vm!
All done with dofoo.vm!

Stop
#stop script elementå…è®¸æ¨¡æ¿è®¾è®¡è€…åœæ­¢æ‰§è¡Œæ¨¡æ¿å¼•æ“ŽåÆˆ˜q”回。把它应用于debug是很有帮助的ã€?
  #stop

Velocimacros
#macro script element允许模板设计者定义一ŒDµå¯é‡ç”¨çš„VTL template。例如:
  #macro ( d )
  <tr><td></td></tr>
  #end
在上面的例子中Velocimacroè¢«å®šä¹‰äØ“dåQŒç„¶åŽä½ ž®±å¯ä»¥åœ¨ä»ÖM½•VTL directive中以如下方式调用它:
  #d()
当你的template被调用时åQŒVelocityž®†ç”¨<tr><td></td></tr>替换ä¸?d()ã€?
每个Velocimacro可以拥有ä»ÀL„æ•°é‡çš„参数――甚è‡?个参敎ͼŒè™½ç„¶å®šä¹‰æ—¶å¯ä»¥éšæ„è®¾¾|®å‚数数量,但是调用˜q™ä¸ªVelocimacroæ—¶å¿…™åÀLŒ‡å®šæ­£¼‹®çš„参数。下面是一个拥有两个参数的VelocimacroåQŒä¸€ä¸ªå‚数是color另一个参数是arrayåQ?
  #macro ( tablerows $color $somelist )
  #foreach ( $something in $somelist )
    <tr><td bgcolor=$color>$something</td</tr>
  #end
  #end
调用#tablerows VelocimacroåQ?
  #set ( $greatlakes = [ “Superior”, “Michigan”, “Huron”, “Erie”, “Ontario” ] )
  #set ( $color = “blue” )
  <table>
    #tablerows( $color $greatlakes )
  </table>
¾lè¿‡ä»¥ä¸Šçš„调用将产生如下的显½Cºç»“果:
  <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>
Velocimacros可以在Velocity模板内实现行内定义(inlineåQ‰ï¼Œä¹Ÿå°±æ„å‘³ç€åŒä¸€ä¸ªweb site内的其他Velocity模板不可以获得Velocimacros的定义。定义一个可以被所有模板共享的Velocimacro昄¡„¶æ˜¯æœ‰å¾ˆå¤šå¥½å¤„ 的:它减ž®‘了在一大堆模板中重复定义的数量、节省了工作旉™—´ã€å‡ž®‘了出错的几率、保证了单点修改ã€?
上面定义çš?tablerows( $color $list )Velocimacro被定义在一个Velocimacros模板åº?在velocity.properties中定ä¹?里,所以这个macro可以åœ? ä»ÖM½•规范的模板中被调用。它可以被多‹Æ¡åº”ç”¨åÆˆä¸”å¯ä»¥åº”ç”¨äºŽä¸åŒçš„ç›®çš„ã€‚ä¾‹å¦‚ä¸‹é¢çš„è°ƒç”¨åQ?
  #set ( $parts = [ “volva”, “stipe”, “annulus”, “gills”, “pileus” ] )
  #set ( $cellbgcol = “#CC00FF” )
  <table>
    #tablerows( $cellbgcol $parts )
  </table>
上面VTLž®†äñ”生如下的输出åQ?
  <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”> pileus </td</tr>
  </table>
  Velocimacro arguments
  Velocimacro可以使用以下ä»ÖM½•å…ƒç´ ä½œäØ“å‚æ•°åQ?
l  ReferenceåQšä“Q何以$开头的reference
l  String literalåQ?
l  Number literalåQ?
l  IntegerRangeåQš[1….3]或者[$foo….$bar]
l  对象数组åQš[“a”,”b”,”c”]
l  booleanå€û|¼štrue、false
当将一个referenceä½œäØ“å‚æ•°ä¼ é€’ç»™Velocimacroæ—Óž¼Œè¯äh³¨æ„referenceä½œäØ“å‚æ•°æ—¶æ˜¯ä»¥åå­—çš„å½¢å¼ä¼ é€’çš„ã€‚è¿™ž®±æ„å‘³ç€å‚æ•° 的值在每次Velocimacro内执行时才会被äñ”生。这个特性ä‹É得你可以ž®†ä¸€ä¸ªæ–¹æ³•调用作为参æ•îC¼ é€’ç»™VelocimacroåQŒè€Œæ¯‹Æ? Velocimacro执行旉™ƒ½æ˜¯é€šè¿‡˜q™ä¸ªæ–ÒŽ³•调用产生不同的值来执行的。例如:
  #macro ( callme $a )
    $a $a $a
  #end
  #callme( $foo.bar() )
执行的结果是åQšreference $fooçš„baråQˆï¼‰æ–ÒŽ³•被执行了三次ã€?
如果你不需要这æ ïLš„ç‰ÒŽ€§å¯ä»¥é€šè¿‡ä»¥ä¸‹æ–ÒŽ³•åQ?
  #set ( $myval = $foo.bar() )
  #callme ( $myval )

Velocimacro properties
Velocity.propertiesæ–‡äšg中的某几行能够ä‹ÉVelocimacros的实现更加灵‹z…R€‚注意更多的内容可以看Developer Guideã€?
Velocity.propertiesæ–‡äšg中的velocimacro.libraaryåQšä¸€ä¸ªä»¥é€—号分隔的模板库列表。默认情况下åQŒvelocity查找唯一的一个库åQšVM_global_library.vm。你可以通过配置˜q™ä¸ªå±žæ€§æ¥æŒ‡å®šè‡ªå·±çš„æ¨¡æ¿åº“ã€?
Velocity.propertiesæ–‡äšg中的velocimacro.permissions.allow.inline属性:有两个可选的 值true或者falseåQŒé€šè¿‡å®ƒå¯ä»¥ç¡®å®šVelocimacros是否可以被定义在regular template内。默认值是ture――允许设计者在他们自己的模板中定义Velocimacrosã€?
Velocity.propertiesæ–‡äšg中的
velocimacro.permissions.allow.inline.replace.global属性有两个可选值trueå’? falseåQŒè¿™ä¸ªå±žæ€§å…è®æ€‹É用者确定inlineçš„Velocimacro定义是否可以替代全局Velocimacro定义åQˆæ¯”如在 velocimacro.library属性中指定的文件内定义的VelocimacroåQ‰ã€‚默认情况下åQŒæ­¤å€égØ“false。这样就é˜ÀL­¢æœ¬åœ° Velocimacro定义覆盖全局定义ã€?
Velocity.propertiesæ–‡äšg中的
velocimacro.permissions.allow.inline.local.scale属性也是有trueå’Œfalse两个可é€? å€û|¼Œé»˜è®¤æ˜¯false。它的作用是用于¼‹®å®šä½ inline定义的Velocimacros是否仅仅在被定义的template内可见。换句话è¯ß_¼Œå¦‚æžœ˜q™ä¸ª 属性设¾|®äØ“trueåQŒä¸€ä¸ªinline定义的Velocimacros只能在定义它的template内ä‹É用。你可以使用此设¾|®å®žçŽîC¸€ä¸ªå¥‡å¦™çš„VMæ•? 门:a template can define a private implementation of the second VM that will be called by the first VM when invoked by that template. All other templates are unaffectedã€?
Velocity.propertiesæ–‡äšg中的velocimacro.context.localscope属性有trueå’Œfalse两个 可选å€û|¼Œé»˜è®¤å€égØ“false。当讄¡½®ä¸ºtrueæ—Óž¼Œä»ÖM½•在Velocimacro内通过#set()对contextçš„ä¿®æ”¹è¢«è®¤äØ“æ˜¯é’ˆå¯ÒŽ­¤ velocimacro的本地设¾|®ï¼Œè€Œä¸ä¼šæ°¸ä¹…的影响内容ã€?
Velocity.propertiesæ–‡äšg中的velocimacro.library.autoreload属性控制Velocimacro 库的自动加蝲。默认是false。当讄¡½®ä¸ºtureæ—Óž¼Œå¯¹äºŽä¸€ä¸ªVelocimacro的调用将自动‹‚€æŸ¥åŽŸå§‹åº“æ˜¯å¦å‘ç”Ÿäº†å˜åŒ–ï¼Œå¦‚æžœå˜åŒ–ž®†é‡æ–°åŠ è½½å®ƒã€‚è¿™ 个属性ä‹É得你可以不用重新启动servlet容器而达到重新加载的效果åQŒå°±åƒä½ ä½¿ç”¨regular模板一栗÷€‚这个属性可以ä‹É用的前提ž®±æ˜¯resource loader¾~“存是off状态(file.resource.loader.cache = falseåQ‰ã€‚注意这个属性实际上是针对开发而非产品的ã€?
Velocimacro Trivia
Velocimacro必须被定义在他们被ä‹É用之前。也ž®±æ˜¯è¯ß_¼Œä½ çš„#macro()声明应该出现在ä‹É用Velocimacros之前ã€?
特别要注意的是,如果你试å›?parse()一个包å?macro()的模æÑ€‚å› ä¸?parse()发生在运行期åQŒä½†æ˜¯è§£æžå™¨åœ? parsetiem军_®šä¸€ä¸ªçœ‹ä¼¼VM元素的元素是否是一个VM元素åQŒè¿™æ ?parse()-ing一¾l„VM声明ž®†ä¸æŒ‰ç…§é¢„æœŸçš„æ ·å­å·¥ä½œã€‚äØ“äº†å¾—åˆ°é¢„æœŸçš„¾l? 果,只需要你½Ž€å•的使用velocimacro.library使得Velocity在启动时加蝲你的VMsã€?
Escaping VTL directives
VTL directives can be escaped with “"”åøP¼Œä½¿ç”¨æ–¹å¼è·ŸVTLçš„reference使用逃逸符的格式差不多ã€?
  ## #include( “a.txt” ) renders as <ontents of a.txt>(注释è¡?
  #include( “a.txt” )

  ## "#include( “a.txt” ) renders as "#include( “a.txt” )
  "#include( “a.txt” )

  ## ""#include ( “a.txt” ) renders as "<contents of a.txt>
  ""#include( “a.txt” )
在对在一个directive内包含多个script元素的VTL directives使用逃逸符时要特别ž®å¿ƒåQˆæ¯”如在一个if-else-end statement内)。下面是VTLçš„if-statement的典型应用:
  #if ( $jazz )
    Vyacheslav Ganelin
  #end
如果$jazz是tureåQŒè¾“出将是:
  Vyacheslav Ganelin
如果$jazz是falseåQŒå°†æ²¡æœ‰è¾“出。ä‹É用逃逸符ž®†æ”¹å˜è¾“出。考虑一下下面的情况åQ?
  "#if ( $jazz )
    Vyacheslav Ganelin
  "#end
现在无论$jazz是true˜q˜æ˜¯falseåQŒè¾“出结果都是:
  #if ( $jazz )
    Vyacheslav Ganelin
  #end
事实上,ç”׃ºŽä½ ä‹É用了逃逸符åQ?jazzæ ÒŽœ¬ž®±æ²¡æœ‰è¢«è§£æžä¸ºboolean型倹{€‚在逃逸符前ä‹É用逃逸符是合法的åQŒä¾‹å¦‚:
  ""#if ( $jazz )
    Vyacheslav Ganelin
  ""#end
以上½E‹åºçš„æ˜¾½Cºç»“æžœäØ“åQ?
  " Vyacheslav Ganelin
  但是如果$jazz为falseåQŒé‚£ä¹ˆå°†æ²¡æœ‰è¾“出。(书上说会没有输出åQŒä½†æ˜¯æˆ‘觉得应该˜q˜æœ‰æœ?#8220;"”字符被输出。)
VTLåQšFormatting issues
ž®½ç®¡åœ¨æ­¤ç”¨æˆ·æ‰‹å†Œä¸­VTL通常都开始一个新行,如下所½Cºï¼š
  #set ( $imperial = [ “Munetaka”, “Koreyasu”, “Hisakira”, “Morikune” ] )
  #foreach ( $shogun in $imperial )
    $shogun
  #end
但是像下面这¿Uå†™æ³•也是可以的åQ?
  Send me #set($foo = [“$10 and”,”a cake”])#foreach($a in $foo)$a #end please.
上面的代码可以被改写为:
  Send me
  #set ( $foo = [“$10 and “,”a cake”] )
  #foreach ( $a in $foo )
    $a
  #end
  please.
或�
  Send me
  #set($foo = [“$10 and “,”a cake”])
        #foreach åQ?a in $foo åQ?a
      #end please.
˜q™ä¸¤¿Uçš„输出¾l“æž„ž®†ä¸€æ —÷€?
å…¶ä»–ç‰ÒŽ€§å’Œæ‚项
  math   在模板中可以使用Velocity内徏的算术函敎ͼŒå¦‚:加、减、乘、除
    #set ( $foo = $bar + 3 )
    #set ( $foo = $bar - 4 )
    #set ( $foo = $bar * 6 )
    #set ( $foo = $bar / 2 )
  当执行除法时ž®†è¿”回一个Integer¾cÕdž‹çš„结果。而余æ•îC½ å¯ä»¥ä½¿ç”¨%来得刎ͼš
    #set ( $foo = $bar % 5 )
在Velocity内ä‹É用数学计½Ž—公式时åQŒåªèƒ½ä‹É用像-n,-2,-1,0,1,2,n˜q™æ ·çš„æ•´æ•ŽÍ¼Œè€Œä¸èƒ½ä‹É用其它类型数据。当一个非整型的对象被使用时它ž®†è¢«loggedòq¶ä¸”ž®†ä»¥nullä½œäØ“è¾“å‡º¾l“æžœã€?
Range Operator
Range operator可以被用于与#setå’?foreach statement联合使用。对于处理一个整型数¾l„它是很有用的,Range operatorå…ähœ‰ä»¥ä¸‹æž„造åŞ式:
  [n..m]
må’Œn都必™åÀL˜¯æ•´åž‹åQŒè€Œm是否大于n则无关紧要。例子:
  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

  Fourth example:
  [1..3]
ä¸Šé¢å››ä¸ªä¾‹å­çš„è¾“å‡ºç»“æžœäØ“åQ?
  First exampleåQ?
  1 2 3 4 5

  Second exampleåQ?
  2 1 0 -1 -2

  Third exampleåQ?
  0 1

  Fourth exampleåQ?
  [1..3]
注意åQšrange operator只在#setå’?foreach中有效ã€?
Advanced IssueåQšEscaping andåQ?
当一个referenceè¢?#8220;åQ?#8221;分隔æ—Óž¼Œòq¶ä¸”在它之前有逃逸符æ—Óž¼Œreferencež®†ä»¥ç‰ÒŽ®Šçš„æ–¹å¼å¤„理。注意这¿Uæ–¹å¼ä¸Žæ ‡å‡†çš„逃逸方式时不同的。对照如下:
#set ( $foo = “bar” )
ç‰ÒŽ®Šå½¢å¼  标准格式
Render�nbsp; Render�nbsp; Render�nbsp; Render�
$"!foo  $!foo  "$foo  "$foo
$"!{foo}  $!{foo}  "$!foo  "$!foo
$""!foo  $"!foo  "$!{foo}  "$!{foo}
$"""!foo  $""!foo  ""$!{foo}  "bar
Velocimacro杂记
  Can I user a directive or another VM as an argument to a VM?
  例如åQ?center ( #bold( “hello” ) )
  不可以。一个directive的参æ•îC‹É用另外一个directive是不合法的ã€?
  但是åQŒè¿˜æ˜¯æœ‰äº›äº‹æƒ…你可以作的。最½Ž€å•的方式ž®±æ˜¯ä½¿ç”¨åŒå¼•åøP¼š
    #set ( $stuff = “#bold( ‘hello’ )” )
    #center ( $stuff )
  上面的格式也可以¾~©å†™ä¸ÞZ¸€è¡Œï¼š
    #center ( “#bold( ‘hello’ ) )
è¯äh³¨æ„åœ¨ä¸‹é¢çš„例子中参数被evaluated在Velocimacro内部åQŒè€Œä¸æ˜¯åœ¨calling level。例子:
  #macro ( inner $foo )
    inner : $foo
  #end

  #macro ( outer $foo )
    #set ( $bar = “outerlala” )
    outer : $foo
  #end
 
  #set ( $bar = ‘calltimelala’ )
  #outer( “#inner($bar)” )
输出¾l“果为:
  outer : inner : outerlala
è®îC½Veloctiy的特性:参数的传递是By Name的。例如:
  #macro ( foo $color )
    <tr bgcolor = $color ><td>Hi</td></tr>
    <tr bgcolor = $color ><td>There</td></tr>
  #end

  #foo ( $bar.rowColor() )
以上代码ž®†å¯¼è‡´rowColor()æ–ÒŽ³•两次调用åQŒè€Œä¸æ˜¯ä¸€‹Æ¡ã€‚äØ“äº†é¿å…è¿™¿UçŽ°è±¡çš„å‡ºçŽ°åQŒæˆ‘们可以按照下面的方式执行åQ?
  #set ( $color = $bar.rowColor() )
  #foo ( $color )
can I register velocimacros via #parse()?
目前åQŒVelocimacros必须在第一‹Æ¡è¢«æ¨¡æ¿è°ƒç”¨å‰è¢«å®šä¹‰ã€‚è¿™ž®±æ„å‘³ç€ä½ çš„#macro()声明应该出现在ä‹É用Velocimacros之前ã€?
如果你试å›?parse()一个包å?macro() directive的模板,˜q™ä¸€ç‚ÒŽ˜¯éœ€è¦ç‰¢è®°çš„。因ä¸?parse()发生在运行期åQŒä½†æ˜¯è§£æžå™¨åœ¨parsetiem军_®šä¸€ä¸ªçœ‹ä¼¼VM元素的元素是否是一 个VM元素åQŒè¿™æ ?parse()-ing一¾l„VM声明ž®†ä¸æŒ‰ç…§é¢„æœŸçš„æ ·å­å·¥ä½œã€‚äØ“äº†å¾—åˆ°é¢„æœŸçš„¾l“æžœåQŒåªéœ€è¦ä½ ½Ž€å•的使用 velocimacro.library使得Velocity在启动时加蝲你的VMsã€?
What is velocimacro autoreloadingåQ?
velocimacro.library.autoreloadæ˜¯ä¸“é—¨äØ“å¼€å‘è€Œéžäº§å“ä½¿ç”¨çš„ä¸€ä¸ªå±žæ€§ã€‚æ­¤å±žæ€§çš„é»˜è®¤å€¼æ˜¯falseã€?
String concatenation
开发äh员最帔R—®çš„问题是我如何作字符拼接åQŸåœ¨java中是使用“åQ?#8221;åäh¥å®Œæˆçš„ã€?
在VTL里要惛_®žçŽ°åŒæ ïLš„功能你只需要将需要联合的reference攑ֈ°ä¸€èµ·å°±è¡Œäº†ã€‚例如:
#set ( $size = “Big” )
#set ( $name = “Ben” )
The clock is $size$name.
输出¾l“æžœž®†æ˜¯åQšThe clock is BigBen.。更有趣的情冉|˜¯åQ?
  #set ( $size = “Big” )
  #set ( $name = “Ben” )
  #set ( $clokc = “$size$name” )
  The clock is $clock.
上例也会得到同样的结果。最后一个例子,当你希望混合固定字段åˆîC½ çš„referenceæ—Óž¼Œä½ éœ€è¦ä‹É用标准格式:
  #set ( $size = “Big” )
  #set ( $name = “Ben” )
  #set ( $clock = “${size}Tall$name” )
  The clock is $clock.
输出¾l“果是:The clock is BigTallBen.。ä‹É用这¿Uæ ¼å¼ä¸»è¦æ˜¯ä¸ÞZº†ä½¿å¾—$size不被解释ä¸?sizeTallã€?

]]>
Ö÷Õ¾Ö©Öë³ØÄ£°å£º ÕÄÆÖÏØ| ƽÓßÏØ| ÙñÖÝÊÐ| ÐÅ·áÏØ| ²ìÑÅÏØ| ¸ÊÂåÏØ| ÑôÐÂÏØ| Î÷¹±Çø| ½ÒÑôÊÐ| ·ïɽÊÐ| ±±°²ÊÐ| ÓÀ¸£ÏØ| É£ÈÕÏØ| ÎÚÀ­ÌØÇ°Æì| ÐËÂ¡ÏØ| ¹ðÑôÏØ| Ä«ÓñÏØ| ÁÙ³ÇÏØ| Ì«¿µÏØ| »¨Ô«ÏØ| ºÍÕþÏØ| ¿í³Ç| аͶû»¢×óÆì| ʯʨÊÐ| ¿ª½­ÏØ| Æ½Ò£ÏØ| °×ɽÊÐ| ƽÏçÏØ| ¿íµé| ½£¸óÏØ| ÐÂÖ£ÊÐ| ¸ÓÓÜÏØ| °¢¿ËÌÕÏØ| ËçµÂÏØ| çÆÔÆÏØ| ÕÑËÕÏØ| ½­É½ÊÐ| Á¬ÖÝÊÐ| ÆÖ½­ÏØ| ½­ÃÅÊÐ| ÂåÄÏÏØ|