velocity使用容易出现诡异情况

1、循环中

#foreach($item in $detail.items)  
#set($name=$item.name)  
$!name  
#end  

 

#foreach($item in $detail.items) #set($name=$item.name) $!name #end

假设$detail.items 有三个元素,第一个元素$item.name="餐巾", 第二个元素$item.name=null ,第三个元素$item.name="手帕"。那么这里会出现什么情况呢?

你可能希望打印的结果是   餐巾  手帕 ,不过,事实不是你想的那样,最终结果会是 餐巾  餐巾  手帕。因为velocity的一个特性就是如果后面的赋值表达式右边为空,那么左边的变量仍然是原来的值,不会被改变。

解决办法:

 1. 使用之前将其给一个初始值

#foreach($item in $detail.items)  
      #set($name="")    
      #set($name=$item.name)  
      $!name  
#end 
 

#foreach($item in $detail.items) #set($name="") #set($name=$item.name) $!name #end

这种问题也经常发生在一些不正确使用#set的场合,例如

#if(......)  
   #set($test=$xxx.xx)  
#end  
 

#if(......) #set($test=$xxx.xx) #end

万一这个$test在前面本身就有某个值,那么这里的判断即使是true,如果$xxx.xx为空也会导致出现结果不正确,因此,在赋值之前给其一 个初始值就显得很有必要

 

#set($test=false)  ## 首先初始化一下,防止出现其他不必要的值  
 #if(......)  
   #set($test=$xxx.xx)  
#end  
 

#set($test=false) ##首先初始化一下,防止出现其他不必要的值 #if(......) #set($test=$xxx.xx) #end

 解决办法2: directive.set.null.allowed=true //这个设置允许#set的表达式右边不存在时将左边变量赋值为null.

2. 模板中使用了#parse,或者调用了#macro定义的宏

  例如:testA.vm中有如下代码:

#macro (method1 $t)  
      #set($t=7)  
      #set($test2=8)  
 #end  
  
   #set($test=5)  
   #parse('testB.vm')  
    $test  ##A  
    #set($test2=5)  
   #method1($test)  
    $test  ##B  
    $test2 ##C  
 

#macro (method1 $t) #set($t=7) #set($test2=8) #end #set($test=5) #parse('testB.vm') $test ##A #set($test2=5) #method1($test) $test ##B $test2 ##C

  testB.vm中有如下代码

   #set($test=6)

这里的输出结果多半会令你吃惊,##A处的应该打印出6 ,##B处应该打印出7,##C处应该打印出8.

why? 记住一点即可,在模板中或者宏中调用 #parse以及另外的宏时,他们都公用一套context上下文,无论你什么地方#set()其实都是改变了这个context中的变量值,因此,这就 要求在#parse或者调用别人的宏时要注意模板中本身的变量被别人给修改掉了,一但发生这个情况,那么杯具,问题很难找,只有一段一段debug.

 另外提到一点,关于宏中为什么对$t进行修改,也会影响到外部的$test,这一点一定要和我们的函数调用区分开,宏并不是函数,这里$t只 是$test的一个别名而已,因此即使你对$t进行修改也会直接影响到$test。

解决办法:

   1.对于#marco目前可以通过设置velocimacro.context.localscope=true,此时,#marco宏内部还是可以直接 无需参数直接使用全局变量,但是如果对全局变量直接进行#set, 即直接替换引用,此时相当于在内部申明了局部变量,#set不会影响到外部的变量。==注:即使设置了这个配置,也不能直接对宏的参数进行#set,否则 会一样会影响到外部,这个bug会在1.7beta1版本中得到解决。

  2. 对#parse据了解没有,但可以通过修改#parse解析类的目的来达到同样的效果。

笔者注:

 到了1.7beta1版本时,之前的有一些已经不推荐使用。

 1. $velocityCount    推荐使用 $foreach.count or $foreach.index

 2. $velocityHasNext  推荐使用  $foreach.hasNext, $foreach.first or $foreach.last

 配置中velocimacro.context.localscope 叶不再推荐使用,因为1.7开始velocity提供了一系列的provide.scope.control,例如

 template.provide.scope.control = true
 evaluate.provide.scope.control = true
 foreach.provide.scope.control = true
 macro.provide.scope.control = true
 define.provide.scope.control = false
 <bodymacroname>.provide.scope.control = false

如果开启这些功能,那么在相应的指令中可以通过使 用$template,$macro等定义局部变量,如 #set($macro.test=true), 如果没有这些前缀,velcoity会当场全局变量来使用。

重要的2.0以后这些不推荐使用的配置将会被清除,不再支持。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值