Skip to content

4.1 消息表达式

正如我们所知,#{...} 消息表达式能将模板中的这段代码:

html
<p th:utext="#{home.welcome}">Welcome to our grocery store!</p>

关联到属性文件中的这段配置:

properties
home.welcome=¡Bienvenido a nuestra tienda de comestibles!

但有一个场景我们尚未考虑:如果消息文本并非完全静态该怎么办?比如,应用能识别当前访问的用户,我们想通过用户名向其问好:

html
<p>¡Bienvenido a nuestra tienda de comestibles, John Apricot!</p>

这就需要给消息添加参数,格式如下:

properties
home.welcome=¡Bienvenido a nuestra tienda de comestibles, {0}!

参数的格式遵循 java.text.MessageFormat 标准语法——这意味着你可以按照 java.text.* 包下相关类的 API 文档,对数字、日期等进行格式化。

假设 HTTP 会话中有一个名为 user 的属性,要为消息参数指定值,我们可以这样写:

html
<p th:utext="#{home.welcome(${session.user.name})}">
  Welcome to our grocery store, Sebastian Pepper!
</p>

INFO

⚠️ 注意:这里使用 th:utext 意味着格式化后的消息不会被转义,因此示例中默认 user.name 已经过转义处理(避免 XSS 风险)。

如果需要传递多个参数,只需用逗号分隔即可。 消息的键本身也可以来自变量(动态指定):

html
<p th:utext="#{${welcomeMsgKey}(${session.user.name})}">
  Welcome to our grocery store, Sebastian Pepper!
</p>

这里 welcomeMsgKey 是上下文变量,Thymeleaf 会先解析 ${welcomeMsgKey} 得到消息键,再结合参数渲染最终文本。

核心语法解释

  1. 消息参数的底层逻辑: Thymeleaf 底层调用 MessageFormat.format(message, params) 处理带参数的消息,{0}{1} 对应参数列表的索引,支持数字、日期、字符串等类型的格式化(如 {0,date,yyyy-MM-dd} 格式化日期)。
  2. 动态消息键的执行顺序#{${welcomeMsgKey}(...)} 会先执行内层的 ${welcomeMsgKey} 解析出消息键,再执行外层的 #{键(参数)} 渲染消息。
  3. th:utext 的使用原则: 仅当消息内容(包括参数)是可信的系统内置文本时使用,若参数来自用户输入,需先手动转义或改用 th:text(自动转义)。

总结

  1. 消息表达式 #{...} 支持通过 {0}/{1} 定义参数,遵循 MessageFormat 语法,可传递单个/多个动态参数。
  2. 消息键也可通过变量 ${...} 动态指定,实现更灵活的多语言逻辑。
  3. 使用 th:utext 渲染带参数的消息时,需确保参数内容安全(已转义),避免 XSS 攻击。