Skip to content

4.15 预处理

除了常规的表达式处理能力外,Thymeleaf 还提供了预处理表达式的特性。

预处理是在常规表达式执行之前完成的一次表达式运算,其核心作用是修改最终要执行的表达式内容,让表达式本身可以动态生成。

预处理表达式的语法和常规表达式完全一致,只是需要用双下划线 __ 包裹(格式:__${表达式}__)。

假设我们有国际化配置文件,其中的消息值本身包含 OGNL 表达式(调用语言相关的静态方法):

  • Messages_fr.properties(法语):
    properties
    article.text=@myapp.translator.Translator@translateToFrench({0})
  • Messages_es.properties(西班牙语):
    properties
    article.text=@myapp.translator.Translator@translateToSpanish({0})

我们需要根据当前语言环境(Locale),动态执行对应语言的翻译方法。此时可以先通过预处理选择要执行的表达式,再让 Thymeleaf 执行最终的表达式:

html
<!-- 第一步:预处理解析 #{article.text('textVar')} 得到对应语言的静态方法表达式;第二步:执行该表达式 -->
<p th:text="${__#{article.text('textVar')}__}">Some text here...</p>

以法语环境为例,Thymeleaf 执行预处理生成的表达式,最终等价于:

html
<p th:text="${@myapp.translator.Translator@translateToFrench(textVar)}">Some text here...</p>

若需要在属性中输出双下划线 __ 本身(而非作为预处理标记),需用 \_\_. 转义。

核心规则与注意事项

  1. 预处理的本质:动态生成表达式: 预处理的核心不是计算表达式的“值”,而是计算“表达式本身”——比如上面的例子中,预处理把 ${__#{article.text('textVar')}__} 转换成了 ${@myapp.translator.Translator@translateToFrench(textVar)},再执行这个新表达式。

  2. 适用场景

    • 国际化动态表达式(如示例中的多语言静态方法调用);
    • 动态选择变量/方法名(比如根据环境选择 devServiceprodService);
    • 复杂表达式的动态拼接(常规表达式无法直接实现的“表达式级别的动态”)。
  3. 预处理与常规表达式的区别

    阶段作用示例(法语环境)
    预处理生成最终要执行的表达式__#{article.text('textVar')}__ 转为 @myapp.translator.Translator@translateToFrench(textVar)
    常规执行计算最终表达式的值调用 translateToFrench(textVar) 得到翻译后的文本

简化理解示例

预处理就像“先写公式,再算结果”:

  • 常规表达式:直接写死公式 1+2,执行后得到 3
  • 预处理:先动态生成公式(比如根据条件生成 1+21*2),再执行生成的公式得到结果。

总结

  1. 预处理表达式用 __表达式__ 包裹,作用是在常规表达式执行前动态生成最终要执行的表达式内容;
  2. 核心场景是“表达式本身需要动态变化”(如多语言静态方法调用),常规表达式无法实现这种“表达式级别的动态”;
  3. 预处理的执行分为两步:先解析生成目标表达式,再执行目标表达式;双下划线需转义时用 \_\_.