更多配置


15.1模板解析器

对于Good Thymes Virtual Grocery,我们选择了一个ITemplateResolver名为的实现ServletContextTemplateResolver,它允许我们从Servlet Context获取模板作为资源。

除了让我们能够通过实现ITemplateResolver,Thymeleaf 创建我们自己的模板解析器包括四个开箱即用的实现:

  • org.thymeleaf.templateresolver.ClassLoaderTemplateResolver,将模板解析为类加载器资源,如:
return Thread.currentThread().getContextClassLoader().getResourceAsStream(template);
  • org.thymeleaf.templateresolver.FileTemplateResolver,将模板解析为文件系统中的文件,如:
return new FileInputStream(new File(template));
  • org.thymeleaf.templateresolver.UrlTemplateResolver,将模板解析为URL(甚至是非本地的),如:
return (new URL(template)).openStream();
  • org.thymeleaf.templateresolver.StringTemplateResolver,直接解析模板作为String指定的模板template(或模板名称,在这种情况下显然不仅仅是一个名称):
return new StringReader(templateName);

所有预绑定的实现都ITemplateResolver允许相同的配置参数集,其中包括:

  • 前缀和后缀(如前所见):
templateResolver.setPrefix("/WEB-INF/templates/");
templateResolver.setSuffix(".html");

允许使用与文件名不直接对应的模板名称的模板别名。如果同时存在后缀/前缀和别名,则将在前缀/后缀之前应用别名:

templateResolver.addTemplateAlias("adminHome","profiles/admin/home");
templateResolver.setTemplateAliases(aliasesMap);

读取模板时要应用的编码:

templateResolver.setEncoding("UTF-8");

要使用的模板模式:

// Default is HTML
templateResolver.setTemplateMode("XML");
  • 模板缓存的默认模式,以及用于定义特定模板是否可缓存的模式:
// Default is true
templateResolver.setCacheable(false);
templateResolver.getCacheablePatternSpec().addPattern("/users/* ");
  • 解析模板缓存条目的TTL(以毫秒为单位)源自此模板解析程序。如果未设置,从缓存中删除条目的唯一方法是超过缓存最大大小(将删除最旧的条目)。
// Default is no TTL (only cache size exceeded would remove entries)
templateResolver.setCacheTTLMs(60000L);

Thymeleaf + Spring集成包提供了一个SpringResourceTemplateResolver实现,它使用所有Spring基础结构来访问和读取应用程序中的资源,这是在启用Spring的应用程序中推荐的实现。

链接模板解析器

此外,模板引擎可以指定多个模板解析器,在这种情况下,可以在它们之间建立订单以进行模板解析,这样,如果第一个无法解析模板,则会询问第二个,依此类推:

ClassLoaderTemplateResolver classLoaderTemplateResolver = new ClassLoaderTemplateResolver();
classLoaderTemplateResolver.setOrder(Integer.valueOf(1));

ServletContextTemplateResolver servletContextTemplateResolver =
        new ServletContextTemplateResolver(servletContext);
servletContextTemplateResolver.setOrder(Integer.valueOf(2));

templateEngine.addTemplateResolver(classLoaderTemplateResolver);
templateEngine.addTemplateResolver(servletContextTemplateResolver);

当应用多个模板解析器时,建议为每个模板解析器指定模式,以便Thymeleaf可以快速丢弃那些不打算解析模板的模板解析器,从而提高性能。这样做不是必要条件,而是建议:

ClassLoaderTemplateResolver classLoaderTemplateResolver = new ClassLoaderTemplateResolver();
classLoaderTemplateResolver.setOrder(Integer.valueOf(1));
// This classloader will not be even asked for any templates not matching these patterns
classLoaderTemplateResolver.getResolvablePatternSpec().addPattern("/layout/*.html");
classLoaderTemplateResolver.getResolvablePatternSpec().addPattern("/menu/*.html");

ServletContextTemplateResolver servletContextTemplateResolver =
        new ServletContextTemplateResolver(servletContext);
servletContextTemplateResolver.setOrder(Integer.valueOf(2));

如果未指定这些可解析的模式,我们将依赖于ITemplateResolver我们正在使用的每个实现的特定功能。请注意,并非所有实现都可以在解析之前确定模板的存在,因此可以始终将模板视为可解析并打破解析链(不允许其他解析器检查相同的模板),但随后无法阅读真实资源。

ITemplateResolver核心Thymeleaf中包含的所有实现都包含一种机制,允许我们在将资源解析为可解析之前让解析器真正检查资源是否存在。这是旗帜,其作用如下:checkExistence

ClassLoaderTemplateResolver classLoaderTemplateResolver = new ClassLoaderTemplateResolver();
classLoaderTemplateResolver.setOrder(Integer.valueOf(1));
classLoaderTempalteResolver.setCheckExistence(true);

此checkExistence标志强制解析器在解析阶段执行资源存在的实际检查(如果存在检查返回false,则调用链中的后续解析器)。虽然这在每种情况下听起来都不错,但在大多数情况下,这意味着对资源本身的双重访问(一次用于检查存在,另一次用于读取它),并且在某些情况下可能是性能问题,例如基于远程URL模板资源 - 一个潜在的性能问题,无论如何都可以通过使用模板缓存来大大减轻(在这种情况下,模板只会在第一次访问时解析)。

15.2Message Resolvers

我们没有为Grocery应用程序明确指定Message Resolver实现,正如之前所解释的那样,这意味着所使用的实现是一个org.thymeleaf.messageresolver.StandardMessageResolver对象。

StandardMessageResolver是IMessageResolver接口的标准实现,但我们可以根据需要创建自己的,以适应我们的应用程序的特定需求。

Thymeleaf + Spring集成包默认提供一个IMessageResolver实现,它使用标准的Spring方法检索外化消息,使用MessageSource在Spring Application Context中声明的bean。

标准消息解析器

那么如何StandardMessageResolver查找特定模板中请求的消息?

如果模板名称home位于/WEB-INF/templates/home.html,并且所请求的区域设置是,gl_ES则此解析程序将按以下顺序查找以下文件中的消息:

  • /WEB-INF/templates/home_gl_ES.properties
  • /WEB-INF/templates/home_gl.properties
  • /WEB-INF/templates/home.properties

StandardMessageResolver有关完整消息解析机制如何工作的更多详细信息,请参阅该类的JavaDoc文档。

配置消息解析器

如果我们想要向模板引擎添加消息解析器(或更多),该怎么办?简单:

// For setting only one
templateEngine.setMessageResolver(messageResolver);

// For setting more than one
templateEngine.addMessageResolver(messageResolver);

为什么我们想拥有多个消息解析器?出于与模板解析器相同的原因:订购消息解析器,如果第一个消息解析器无法解析特定消息,则会询问第二个,然后是第三个,等等。

15.3转换服务

使我们能够通过双括号语法()执行数据转换和格式化操作的转换服务实际上是标准方言的一个特征,而不是Thymeleaf模板引擎本身。${{...}}

因此,配置它的方法是将IStandardConversionService接口的自定义实现直接设置到StandardDialect正在配置到模板引擎中的实例中。喜欢:

IStandardConversionService customConversionService = ...

StandardDialect dialect = new StandardDialect();
dialect.setConversionService(customConversionService);

templateEngine.setDialect(dialect);

请注意,thymeleaf-spring3和thymeleaf-spring4软件包包含SpringStandardDialect,并且此方言已预先配置了IStandardConversionService将Spring自己的转换服务基础结构集成到Thymeleaf中的实现。

15.4记录

Thymeleaf非常关注日志记录,并始终尝试通过其日志记录界面提供最大量的有用信息。

使用的日志库slf4j,实际上充当了我们可能希望在我们的应用程序中使用的任何日志记录实现的桥梁(例如,log4j)。

Thymeleaf班会记录TRACE,DEBUG并INFO-level信息,这取决于我们希望的详细程度,并且除了一般的记录它会使用与TemplateEngine类,我们可以为不同的目的而单独配置相关的三个特殊记录器:

  • org.thymeleaf.TemplateEngine.CONFIG 将在初始化期间输出库的详细配置。
  • org.thymeleaf.TemplateEngine.TIMER 将输出有关处理每个模板所用时间的信息(对基准测试很有用!)
  • org.thymeleaf.TemplateEngine.cache是一组记录器的前缀,用于输出有关高速缓存的特定信息。虽然缓存记录器的名称可由用户配置,因此可能会更改,但默认情况下它们是:
    • org.thymeleaf.TemplateEngine.cache.TEMPLATE_CACHE
    • org.thymeleaf.TemplateEngine.cache.EXPRESSION_CACHE

使用Thymeleaf的日志记录基础结构的示例配置log4j可以是:

log4j.logger.org.thymeleaf=DEBUG
log4j.logger.org.thymeleaf.TemplateEngine.CONFIG=TRACE
log4j.logger.org.thymeleaf.TemplateEngine.TIMER=TRACE
log4j.logger.org.thymeleaf.TemplateEngine.cache.TEMPLATE_CACHE=TRACE