Skip to content

进阶:JS内联的智能求值与对象序列化

Thymeleaf 的 JavaScript 内联不仅支持简单的字符串/数字/布尔值,还具备智能的对象序列化能力——能自动将后端的复杂对象(如 Java Bean、数组、Map、集合)转换为合法的 JavaScript 对象字面量,无需手动拼接 JSON 字符串,极大简化了前后端数据传递。

支持的类型包括:

后端数据类型JS 序列化结果示例(后端 → 前端)
字符串(String)带引号的 JS 字符串(转义)"Sebastian \"Fruity\" Applejuice"
数字(Number)JS 数字字面量28
布尔(Boolean)JS 布尔字面量true/false
数组/集合(Array/Collection)JS 数组["admin", "user"]
MapJS 对象{"key1":"value1", "key2":123}
Java Bean(实体类)JS 对象(按 getter 序列化){"name":"John", "age":28, "isAdmin":true}

我们来看一下下述代码:

html
<script th:inline="javascript">
    ...
    // 注释包裹表达式 + 静态占位符(null)
    var user = /*[[${session.user}]]*/ null;
    ...
</script>

Thymeleaf 会自动将 User 对象序列化为合法的 JS 对象字面量,最终渲染结果:

html
<script th:inline="javascript">
    ...
    var user = {"age":null,"firstName":"John","lastName":"Apricot",
        "name":"John Apricot","nationality":"Antarctica"};
    ...
</script>
  • 静态预览时:user = null(占位符生效,JS 无语法错误);
  • 动态渲染时:user 是完整的 JS 对象,可直接通过 user.name/user.age 访问属性。

Thymeleaf 的 JS 序列化依赖 org.thymeleaf.standard.serializer.IStandardJavaScriptSerializer 接口,该接口可以在模板引擎所使用的 StandardDialect 实例中进行配置。

该 JS 序列化机制的默认实现会在类路径中查找 Jackson 库,如果存在则使用它。如果未找到,则会应用一个内置的序列化机制,该机制能满足大多数场景的需求并产生类似的结果(但灵活性较低)。

关键注意事项

  1. 静态占位符的选择: 序列化复杂对象时,静态占位符建议用 null 或空对象 {},避免静态预览时 JS 报错:
    html
    <!-- 推荐:空对象作为占位符 -->
    var userInfo = /*[[${user.info}]]*/ {};
  2. 避免循环引用: 若后端对象存在循环引用(如 User 包含 OrderOrder 又包含 User),Jackson 序列化会报错,需在实体类中通过 @JsonIgnore@JsonManagedReference 解决;
  3. 数据安全性: 序列化时会包含对象的所有可访问 getter 字段,注意不要将敏感信息(如密码、token)放入序列化对象中;
  4. 性能考量: 序列化超大对象(如包含大量数据的集合)时,会增加页面体积,建议仅传递前端所需的核心字段。

核心优势

  • 无需手动拼接 JSON:避免手写 JSON.stringify() 或拼接字符串导致的语法错误;
  • 原生模板友好:注释+占位符的写法保证静态预览合法,动态渲染正确;
  • 类型安全:自动适配 JS 语法,不会出现「数字加引号」「布尔值字符串化」等问题。

总结

  1. Thymeleaf JS 内联支持复杂对象的智能序列化,可将 Java Bean/Map/数组等直接转为合法的 JS 对象;
  2. 底层优先使用 Jackson 序列化,无 Jackson 时用内置机制兜底,满足绝大多数场景;
  3. 最佳实践:用 /*[[${对象}]]*/ null 写法,兼顾动态序列化和静态预览的合法性;
  4. 注意避免循环引用、敏感数据泄露,超大对象需按需序列化核心字段。