深色模式
进阶: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"] |
| Map | JS 对象 | {"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 库,如果存在则使用它。如果未找到,则会应用一个内置的序列化机制,该机制能满足大多数场景的需求并产生类似的结果(但灵活性较低)。
关键注意事项
- 静态占位符的选择: 序列化复杂对象时,静态占位符建议用
null或空对象{},避免静态预览时 JS 报错:html<!-- 推荐:空对象作为占位符 --> var userInfo = /*[[${user.info}]]*/ {}; - 避免循环引用: 若后端对象存在循环引用(如
User包含Order,Order又包含User),Jackson 序列化会报错,需在实体类中通过@JsonIgnore或@JsonManagedReference解决; - 数据安全性: 序列化时会包含对象的所有可访问 getter 字段,注意不要将敏感信息(如密码、token)放入序列化对象中;
- 性能考量: 序列化超大对象(如包含大量数据的集合)时,会增加页面体积,建议仅传递前端所需的核心字段。
核心优势
- 无需手动拼接 JSON:避免手写
JSON.stringify()或拼接字符串导致的语法错误; - 原生模板友好:注释+占位符的写法保证静态预览合法,动态渲染正确;
- 类型安全:自动适配 JS 语法,不会出现「数字加引号」「布尔值字符串化」等问题。
总结
- Thymeleaf JS 内联支持复杂对象的智能序列化,可将 Java Bean/Map/数组等直接转为合法的 JS 对象;
- 底层优先使用 Jackson 序列化,无 Jackson 时用内置机制兜底,满足绝大多数场景;
- 最佳实践:用
/*[[${对象}]]*/ null写法,兼顾动态序列化和静态预览的合法性; - 注意避免循环引用、敏感数据泄露,超大对象需按需序列化核心字段。
