`
gstarwd
  • 浏览: 1538638 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

velocity使用容易出现诡异情况

阅读更多

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=$xxx.xx)  
#end  
 

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

 

#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  
 

  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以后这些不推荐使用的配置将会被清除,不再支持。

分享到:
评论

相关推荐

    Velocity非常容易学会

    这种分工合作不仅提高了开发效率,还使得项目的长期维护变得更加容易。此外,Velocity还提供了一种不同于JSP和PHP的新选择,使得开发者可以根据项目需求灵活选择技术栈。 #### 二、Velocity模板语法基础 ##### 2.1...

    velocity入门使用教程

    教程内容包含了解Velocity模板引擎的基础知识、学习VTL语法、设置和使用velocity.properties配置文件以及如何在Servlet和Spring MVC环境中集成Velocity。 ### Velocity模板引擎的基本使用方法 Velocity可以用来...

    freemarker&velocity的使用

    1. **引用和指令**:Velocity使用`${variable}`引用变量,而`#set`、`#if`、`#foreach`等指令实现控制结构。与Freemarker相比,Velocity的语法更加简洁。 2. **上下文对象**:在Velocity中,数据模型通常称为“上...

    velocity使用说明doc文档

    Velocity 提供了一种简单而强大的脚本语言——Velocity 模板语言 (VTL),让页面设计者能够在不涉及 Java 代码的情况下插入和处理动态内容。 VTL 的主要特点是通过引用 (references) 来访问和操作由 Java 代码定义的...

    velocity使用

    【Velocity使用详解】 Velocity是一个基于Java的模板引擎,它的核心功能是将模板语言与Java代码相结合,使得非程序员,如网页设计师,能够专注于页面的视觉呈现,而开发者则专注于业务逻辑的实现。这种分离使得开发...

    velocity 使用手冊整理

    **Velocity 模板引擎使用手册整理** Velocity 是一个开源的 Java 模板引擎,它允许开发者将业务逻辑与页面展示分离,使得Web开发更加高效。Velocity 提供了一种简单但强大的语言,用于创建动态HTML、XML或其他格式...

    模板:velocity和freemarker的比较

    在 WebWork2 中,我们可以随意选择使用 Freemarker 或 Velocity 作为 View,模板技术作为 View 的好处是很多,尤其和 JSP 比较起来优点更大。 Velocity 和 Freemarker 都是开源的模板技术,它们都提供了强大的功能...

    Velocity模板使用指南中文版

    ** Velocity 模板使用指南中文版 ** Velocity 是一个基于 Java 的开源模板引擎,它允许开发者将业务逻辑与页面展示分离,使得网页设计者可以专注于页面的布局和样式,而程序员则关注于程序的逻辑处理。Velocity 在 ...

    使用velocity

    ### 使用Velocity进行动态模板渲染的关键知识点 #### 一、Velocity简介与环境搭建 **Velocity**是一种基于Java的模板引擎,用于生成动态HTML页面或其他文本格式的文档。它提供了一种简单而强大的方式来分离业务...

    velocity为空判断

    在使用Velocity作为视图层处理数据时,常常需要进行空值判断,确保模板能够正确地处理不存在或者值为空的情况。下面我们将详细探讨在Velocity中如何进行空值和空字符串的判断。 ### 1. 判断Velocity变量是否为null ...

    velocity模板使用指南中文版

    Velocity 模板使用指南中文版 Velocity 是一种流行的模板引擎,广泛应用于Java 和 .Net 平台。它提供了一个灵活、可扩展的模板语言,能够根据需要生成动态内容。本文档是 Velocity 模板使用指南中文版,旨在帮助...

    velocity文档(Velocity1.4java开发指南中文版,Velocity1.4模板使用指南中文版中文版)

    提供的 "Velocity1.4java开发指南中文版.pdf" 和 "Velocity1.4柾斅巊梡巜撿拞暥斉拞暥斉.pdf" 应该是 Velocity 1.4 的中文版开发文档和使用教程。通过阅读这两份文档,你可以深入学习如何配置 Velocity,如何编写...

    velocity入门使用

    在Java代码中,你需要将数据放入Velocity上下文,以便在模板中使用。例如: ```java VelocityContext context = new VelocityContext(); context.put("name", "John Doe"); context.put("items", itemList); ``` ...

    Velocity 和 FreeMarker区别

    **FreeMarker**相比**Velocity**而言,在大多数情况下更加容易使用。主要原因是FreeMarker内置了更多的功能,例如自动转义机制、丰富的内置函数等,这使得开发者无需额外编写工具类或方法即可完成许多常见的任务。而...

    Velocity用户手册 中文版

    4. **安全**:由于Velocity的模板语言不支持复杂的计算和控制结构,因此它比某些其他模板引擎更安全,不容易引发脚本注入问题。 ** 实际应用 ** Velocity 广泛应用于Web开发中,特别是在基于Apache的项目中,如...

    velocity语法与使用方法

    - 变量引用可以使用`${variable}`或`$variable`两种形式,其中使用大括号的方式可以避免某些情况下出现的错误。 #### 2. 字符串处理 Velocity提供了丰富的字符串处理功能,如拼接、截取等: - 拼接示例:`#set($...

    velocity Java开发指南中文版

    - **Singleton Model**: 介绍如何使用单例模式来管理 Velocity 的实例,适用于大多数情况下的资源管理。 - **Separate Instance**: 有时可能需要为每个请求创建单独的 Velocity 实例,这部分会讨论这种场景下的优...

    velocity-1.5.jar,velocity-1.6.2-dep.jar,velocity-tools-1.3.jar

    在实际使用中,开发者需要将这些JAR文件添加到项目的类路径中,然后可以通过创建VelocityContext对象,填充数据,最后使用Velocity Engine渲染模板。这整个过程是完全独立于具体的服务器环境的,使得Velocity成为一...

    使用了Struts结构和Velocity模板技术的BLOG

    Struts和Velocity是两种在Java Web开发中广泛使用的开源框架,它们在构建高效、可维护的Web应用程序中扮演着重要角色。本项目“使用了Struts结构和Velocity模板技术的BLOG”旨在演示如何结合这两种技术来创建一个...

Global site tag (gtag.js) - Google Analytics