扩展Thymeleaf很容易:只需要创建一个方言并将其添加到模板引擎。 下面来看看,如何一步步地实现。
所有在这里看到的代码都来自一个工作应用程序。可以从GitHub仓库查看或下载源代码。
1. 方言
Thymeleaf方言(Dialects)是可以在模板中使用的一组功能。 这些功能包括:
- 处理逻辑 - 通过适用于标签中的属性的处理器(或标签本身)指定处理逻辑。
- 预处理和后处理逻辑通过预处理器和后处理器指定,实际上在处理之前(之前)或之后(后处理)应用于模板。
- 表达式对象可用于Thymeleaf标准表达式(如
#array
,#dates
等),以执行可能需要的操作。
所有这些功能都是可选的,方言只能指定其中的一部分。 例如,一个方言可能不需要指定任何处理器,但是可以声明几个表达式对象。
如果已经看到用标准方言编写的代码片段,应该注意到,可处理的属性以th:
开头。 这个“th”
被称为方言前缀,这意味着由该方言处理的所有标签和属性将以这样的前缀开头。 每种方言都可以指定自己的前缀。
同样重要的是要注意,一个模板引擎可以一次设置多个方言,从而允许处理包括来自所有指定方言的特征的模板(将方言看作是一种JSP标签库)。 更重要的是,这些方言中的一些可以共享前缀,有效地作为一种方言。
2. 最简单的方言
这里将在应用程序中创建一个方言。 这将是一个Spring MVC应用程序,所以将要已经使用SpringStandard方言(更多细节参见Thymeleaf + Spring教程)。 但是想添加一个新的属性,向请求的客户端显示问候语,如下所示:
<p hello:sayto="World">Hi ya!</p>
2.1 处理器
首先,需要创建属性处理器来处理显问候语消息。
所有处理器都实现org.thymeleaf.processor.IProcessor
接口,特别是标记处理器实现org.thymeleaf.processor.element.IElementTagProcessor
接口,因为它是一个处理器,它适用于元素(以XML/HTML术语),这种元素的开放标签。
另外,这个处理器会被这个开放标签(hello:sayto
)中的指定属性触发,所以将扩展一个有用的抽象类,它将给出大部分的类基础结构:org.thymeleaf.processor.element.AbstractAttributeTagProcessor
。请参考下面代码的实现 -
public class SayToAttributeTagProcessor extends AbstractAttributeTagProcessor {
private static final String ATTR_NAME = "sayto";
private static final int PRECEDENCE = 10000;
public SayToAttributeTagProcessor(final String dialectPrefix) {
super(
TemplateMode.HTML, // This processor will apply only to HTML mode
dialectPrefix, // Prefix to be applied to name for matching
null, // No tag name: match any tag name
false, // No prefix to be applied to tag name
ATTR_NAME, // Name of the attribute that will be matched
true, // Apply dialect prefix to attribute name
PRECEDENCE, // Precedence (inside dialect's precedence)
true); // Remove the matched attribute afterwards
}
protected void doProcess(
final ITemplateContext context, final IProcessableElementTag tag,
final AttributeName attributeName, final String attributeValue,
final IElementTagStructureHandler structureHandler) {
structureHandler.setBody(
"Hello, " + HtmlEscape.escapeHtml5(attributeValue) + "!", false);
}
}
2.2 方言类
创建处理器非常简单,但现在还需要创建方言类,负责告诉Thymeleaf处理器是可用的。
最基本的方言接口:org.thymeleaf.dialect.IDialect
只告诉Thymeleaf一个特定的类是方言。 但是引擎需要知道那个创建的方言能够提供什么,并且声明方言类,需要实现一组或几组IDialect
子接口。
具体来说,out
方言将提供*
处理器,因此它将实现org.thymeleaf.dialect.IProcessorDialect
。 为了更容易一些,这里不是直接实现接口,而是扩展一个名为org.thymeleaf.dialect.AbstractProcessorDialect
的抽象类,参考以下代码:
public class HelloDialect extends AbstractProcessorDialect {
public HelloDialect() {
super(
"Hello Dialect", // Dialect name
"hello", // Dialect prefix (hello:*)
1000); // Dialect precedence
}
/*
* Initialize the dialect's processors.
*
* Note the dialect prefix is passed here because, although we set
* "hello" to be the dialect's prefix at the constructor, that only
* works as a default, and at engine configuration time the user
* might have chosen a different prefix to be used.
*/
public Set<IProcessor> getProcessors(final String dialectPrefix) {
final Set<IProcessor> processors = new HashSet<IProcessor>();
processors.add(new SayToAttributeTagProcessor(dialectPrefix));
return processors;
}
}
3. 使用Hello方言
使用上面创建这个新方言非常简单。 这是一个Spring MVC应用程序,只需在配置期间将它添加到templateEngine
Bean。如下代码所示 -
@Bean
public SpringTemplateEngine templateEngine(){
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setEnableSpringELCompiler(true);
templateEngine.setTemplateResolver(templateResolver());
templateEngine.addDialect(new HelloDialect());
return templateEngine;
}
请注意,通过使用addDialect()
,而不是setDialect()
,告诉引擎除了默认的StandardDialect
之外,还想使用新的方言。 所以所有的标准th:*
属性也将可用。
现在需要新属性可以无缝工作,如下:
<p>Hello World!</p>