velocity使用容易出現詭異的旮旯

2021-09-05 23:42:36 字數 2368 閱讀 4912

1、迴圈中

#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

這種問題也經常發生在一些不正確使用#set的場合,例如

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

萬一這個$test在前面本身就有某個值,那麼這裡的判斷即使是true,如果$***.xx為空也會導致出現結果不正確,因此,在賦值之前給其乙個初始值就顯得很有必要

#set($test=false) ##首先初始化一下,防止出現其他不必要的值 #if(......) #set($test=$***.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

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

.provide.scope.control = false

如果開啟這些功能,那麼在相應的指令中可以通過使用$template,$macro等定義區域性變數,如 #set($macro.test=true), 如果沒有這些字首,velcoity會當場全域性變數來使用。

重要的2.0以後這些不推薦使用的配置將會被清除,不再支援。

velocity使用容易出現詭異的旮旯

1 迴圈中 foreach item in detail.items set name item.name name end 假設 detail.items 有三個元素,第乙個元素 item.name 餐巾 第二個元素 item.name null,第三個元素 item.name 手帕 那麼這裡會出...

velocity 巨集 macro 出現中文亂碼

最開始使用velocity時,輸出中文亂碼,我的解決辦法 是在呼叫 mergetemplate 方法時指定encoding為utf 8,然後就正常了。velocity.mergetemplate string templatename,string encoding,context context,...

使用lombok註解容易出現迴圈依賴

使用lombok註解時需要注意迴圈記憶體溢位,是因為tostring,equal,hashcode 現迴圈物件呼叫,所以需要使用 tostring exclude equalsandhashcode exclude 兩個註解來排除依賴項,防止迴圈依賴出現記憶體溢位問題的bug entity tabl...