Skip to content

16 模板缓存

Thymeleaf 的工作机制依赖两类核心组件:解析器(parsers):将模板(标记型/文本型)解析为事件序列(如标签打开、文本、标签关闭、注释等);处理器(processors):针对不同的模板行为(如 th:textth:each),修改解析后的事件序列,结合业务数据生成最终结果。

Thymeleaf 默认启用模板缓存——缓存的是「模板文件读取并解析后的事件序列」(而非处理后的最终页面),这一设计专为 Web 应用优化,核心依据如下:

  1. IO 操作是性能瓶颈:任何应用中,文件/网络 IO 几乎都是最慢的环节,而内存内处理极快;
  2. 内存克隆更高效:克隆已存在的内存事件序列,远比重新读取模板文件、解析生成新序列快;
  3. Web 应用模板特性:通常只有几十套模板,文件大小为小到中等,且应用运行期间模板文件不会修改。

基于以上特点,缓存 Web 应用中常用的模板,既能避免浪费大量内存,又能省去重复 IO 操作的耗时(模板文件实际从不修改)。

那么我们该如何掌控这一缓存机制呢?首先,我们此前已经了解到,可在模板解析器(Template Resolver)层面启用或禁用缓存 —— 甚至还能仅针对特定模板生效:

java
// 全局禁用缓存(默认是 true,即开启)
templateResolver.setCacheable(false);

// 仅对 /users/* 路径的模板启用缓存(其他模板禁用)
templateResolver.getCacheablePatternSpec().addPattern("/users/*");

此外,我们还可以通过配置自定义的缓存管理器(Cache Manager)对象来修改缓存的相关设置 —— 该对象可以是默认实现类 StandardCacheManager 的一个实例

java
// 创建默认缓存管理器实例
StandardCacheManager cacheManager = new StandardCacheManager();
// 设置模板缓存的最大条目数(默认 200)
cacheManager.setTemplateCacheMaxSize(100);

// 将自定义缓存管理器绑定到模板引擎
templateEngine.setCacheManager(cacheManager);

更多缓存配置细节可参考 org.thymeleaf.cache.StandardCacheManager 的 JavaDoc 文档。

可按需清空全部缓存,或仅清理指定模板的缓存(如模板文件更新后):

java
// 清空整个模板缓存
templateEngine.clearTemplateCache();

// 仅清空 /users/userList 模板的缓存
templateEngine.clearTemplateCacheFor("/users/userList");

核心解析

1. 缓存的本质:事件序列缓存

  • 缓存的是「模板解析后的事件序列」,而非最终渲染的页面(页面数据是动态的,缓存无意义);
  • 每次请求处理时,Thymeleaf 会克隆缓存中的事件序列,再结合动态数据处理生成页面——克隆操作极快,大幅减少解析耗时。

2. 缓存配置的典型场景

配置方式适用场景
全局禁用缓存开发环境(模板文件频繁修改,无需缓存,即时生效)
全局开启 + 特定路径禁用生产环境中,少数需要动态更新的模板(如运营配置模板)
调整缓存最大数量模板数量远超默认 200 时(如大型平台有数百套模板),避免内存溢出
手动清理缓存生产环境中模板文件更新后(无需重启应用,清理对应缓存即可生效)

3. 性能与内存的平衡

  • 模板事件序列的内存占用远小于模板文件本身(解析后是结构化的事件对象);
  • 即使缓存 200 套中等大小的模板,内存占用通常也在 MB 级别,对 Web 应用几乎无压力;
  • 缓存失效策略:默认基于「最大条目数」淘汰(LRU 算法),超出上限时移除最久未使用的模板缓存。

总结

  1. Thymeleaf 模板缓存默认开启,缓存的是「解析后的事件序列」,核心优化 IO 和解析耗时;
  2. 可通过模板解析器精准控制缓存开关,或通过缓存管理器调整缓存容量;
  3. 开发环境建议禁用缓存(即时看到模板修改效果),生产环境开启缓存(最大化性能);
  4. 生产环境更新模板后,可通过手动清理缓存让修改生效,无需重启应用。