Thymeleaf 3.0教程:17 分离模板逻辑(二)
17.2 配置分离模板
启用分离模板
默认情况下,并非每个模板都需要分离逻辑。相反,已配置的模板解析器(ITemplateResolver的实现)将需要专门将它们解析的模板标记为使用分离逻辑。
除了StringTemplateResolver(不允许分离逻辑)之外,ITemplateResolver的所有其他现成实现都将提供一个名为useDecoupledLogic的标志,该标志将该解析器解析的所有模板标记为其逻辑的全部或部分可能位于单独的资源中:
final ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(servletContext); ... templateResolver.setUseDecoupledLogic(true);
混合耦合和去耦逻辑
去耦模板逻辑在启用时不是必需的。启用时,这意味着引擎将寻找包含分离逻辑的资源,解析它并将其与原始模板合并(如果存在的话)。如果分离的逻辑资源不存在,则不会引发错误。
此外,在同一个模板中,我们可以混合耦合和去耦逻辑,例如通过在原始模板文件中添加Thymeleaf属性,而将其他属性留给单独的去耦逻辑文件。最常见的情况是使用新的(在v3.0中)th:ref属性。
17.3 th:ref属性
th:ref只是一个标记属性。从处理的角度来看,它什么也不做,只是在模板被处理时消失,但是它的用处在于它充当标记引用,即它可以通过标记选择器的名称来解析,就像标签名称或片段(th:fragment)一样。
所以如果我们有一个选择器,比如:
<attr sel="whatever" .../>
这将匹配:
所有<whatever>标签.
所有带有th:fragment="whatever"属性的标签。
所有带有th:ref="whatever" 属性的标签。
th:ref的优势是什么?例如,使用纯HTML id属性?事实上,我们可能不想在标签中添加这么多id和类属性来充当逻辑锚,这可能最终会污染我们的输出。
在同样的意义上,th:ref的缺点是什么?显然,我们会在模板中添加一点Thymeleaf逻辑(“logic”)。
请注意,th:ref属性的这种适用性不仅适用于分离的逻辑模板文件:它在其他类型的场景中也同样适用,如片段表达式(~{...})。
17.4 去耦模板的性能影响
影响非常小。当一个已解析的模板被标记为使用分离逻辑并且没有被缓存时,模板逻辑资源将首先被解析,解析并被处理成内存中的一系列指令:基本上是要注入每个标记选择器的属性列表。
但是这是唯一需要的额外步骤,因为在此之后,真正的模板将被解析,并且在解析时,这些属性将由解析器本身动态注入,这要归功于AttoParser中的节点选择高级功能。因此,解析后的节点将从解析器中出来,就好像它们的注入属性被写入了原始模板文件一样。
这最大的好处是什么?当模板被配置为缓存时,它将被缓存为已经包含注入的属性。因此,对可缓存模板使用分离模板的开销,一旦它们被缓存,开销将绝对为零。
17.5 去耦逻辑的解决
Thymeleaf解析对应于每个模板的分离逻辑资源的方式可由用户配置。它由一个继承自org.thymeleaf.templateparser.markup.decoupled.IDecoupledTemplateLogicResolver的类确定,该类提供了一个默认实现:standardDePuledTemplatElecticResolver。
这个标准实现做什么?
首先,它将前缀和后缀应用于模板资源的基本名称(通过其ITemplateResource#getBaseName()方法获得)。前缀和后缀都可以配置,默认情况下,前缀为空,后缀为.th.xml。
其次,它要求模板资源通过其ITemplateResource#relative(字符串相对位置)方法解析具有计算名称的相对资源。
要使用的IDecoupledTemplateLogicResolver的具体实现可以在模板引擎中轻松配置:
final StandardDecoupledTemplateLogicResolver decoupledresolver = new StandardDecoupledTemplateLogicResolver(); decoupledResolver.setPrefix("../viewlogic/"); ... templateEngine.setDecoupledTemplateLogicResolver(decoupledResolver);