接手一个老项目,模板文件后缀是 .vm,里面全是 $ 和 # 开头的写法,看着像坏掉的 HTML。这就是 Velocity,一套基于 Java 的模板引擎,逻辑放在后端,页面只负责取变量和简单判断。

三个核心符号

  • $:取变量,$user.name 或者 ${user.name}。
  • #:指令,比如 #if、#foreach、#set。
  • ##:单行注释,#* ... *# 是多行注释。

变量名后面跟方法调用也支持,$list.size()、$str.toUpperCase(),本质上是在调 Java 对象的方法。

变量取不到会怎样

这是最容易踩的坑。Velocity 默认遇到不存在的变量,会原样把 $name 输出到页面上,而不是报错或者留空。页面上突然出现一串美元符号,基本就是变量名写错了或者后端没塞进去。

${name} 的大括号写法能明确变量边界。像 $user_name 和 $user 后面紧跟文字的情况,不加括号解析结果会出乎意料。

常用指令

#set($title = "订单详情")

#if($status == 1)
  已支付
#elseif($status == 2)
  已发货
#else
  未知
#end

#foreach($item in $items)
  <li>$item.name</li>
#end

注意 #end 是必须的,#if 和 #foreach 都要配对。少了 #end,模板渲染直接抛异常,报错信息往往只指向文件不指向行号,找起来很费劲。

空值和默认值

判断变量是否存在用 #if($obj),注意 0、空字符串、false 在 Velocity 里都算「假」,和 Java 的语义不完全一致。需要区分「null」和「空字符串」,可以用 $obj 与空字符串的比较,或者干脆在后端处理好再传。

Velocity 2.x 支持 $!{name} 这种写法,变量为空时输出空而不是原始符号,比默认行为友好,新项目建议统一用这种写法。

和前端框架共存

页面里同时有 Vue 或者 Angular 时,$ 和 {{ }} 可能冲突。常见的处理是把 Velocity 的输出转义,或者调整前端框架的插值分隔符。混合渲染的项目里,这一块最容易出莫名其妙的问题,调试时先确认某个占位符是被谁吃掉的。

其他要注意的

  • 模板缓存:开发环境记得关缓存,不然改了 vm 文件刷新没反应。
  • XSS:Velocity 默认不做 HTML 转义,用户输入直接输出有风险,后端要转义。
  • 性能:复杂逻辑别写在模板里,模板只做展示,计算放后端。