说声你好!在5分钟内扩展Thymeleaf
扩展Thymeleaf非常简单:我们只需要创建一个方言(dialect)并将其添加到我们的模板引擎中。让我们看看具体怎么操作。
此处展示的所有代码都来自一个可运行的应用程序。你可以查看或下载源代码其 GitHub 仓库.
方言(Dialects)
Thymeleaf中的方言是一组可以在模板中使用的功能。这些功能包括:
- 处理逻辑通过处理器(processors)指定,并应用于我们标签中的属性(或者标签本身)。
- 预处理和后处理逻辑通过预处理器(pre-processors)和和后处理器(post-processors)来指定,并在实际处理发生之前(预处理)或之后(后处理)应用于我们的模板。
- 表达式对象(Expression objects)这些对象可以用在Thymeleaf的标准表达式中(例如
#arrays
,#dates
,等等),以便执行我们可能需要的特定操作。
所有这些功能都是可选的,一个方言可以只定义其中的一部分。例如,某个方言可能不需要定义任何处理器,但可以声明几个表达式对象.
如果你见过用标准方言(Standard Dialects)编写的代码片段,你应该已经注意到,可处理的属性是以th:
开头的。这个“th
”被称为方言前缀(dialect prefix),它意味着该方言处理的所有标签和属性都将以前述前缀开头。每个方言都可以指定自己的前缀。
另外需要注意的是,一个模板引擎可以同时设置多个方言,从而允许处理包含所有指定方言功能的模板(可以把方言想象成一种增强版的JSP标签库(JSP taglibs))。不仅如此,其中一些方言还可以共享前缀,从而有效地表现得像是一个聚合方言一样。
最简单的方言示例:Say Hello!
让我们为其中一个应用创建一个方言。这将是一个Spring MVC应用,因此我们已经在使用SpringStandard方言(更多细节请参阅Thymeleaf + Spring 教程)。但我们想添加一个新的属性,使我们可以向任何人打招呼,如下所示:
<p hello:sayto="World">Hi ya!</p>
处理器(The processor)
首先,我们必须创建负责显示问候语的属性处理器。
所有处理器都实现了org.thymeleaf.processor.IProcessor
接口,而具体的标签处理器则实现org.thymeleaf.processor.element.IElementTagProcessor
接口,因为它是一个应用于元素(element)的处理器(按照XML/HTML术语),更确切地说是应用于该元素的open tag。
此外,这是一个由该开始标签中的特定属性触发的处理器(open tag (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);
}
}
方言类(The dialect class)
创建处理器非常简单,但现在我们需要创建方言类(dialect class),它将告诉Thymeleaf我们的处理器是可用的。
最基础的方言接口org.thymeleaf.dialect.IDialect
,只是告诉Thymeleaf某个类是一个方言(dialect)。但引擎需要知道这个方言能够提供什么功能,为了声明这一点,方言类将实现一组IDialect
子接口(sub-interfaces)中的一个或多个。
具体来说,我们的方言将提供*处理器*,因此它会实现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;
}
}
使用hello方言(Using the hello dialect)
使用我们的新方言非常简单。对于一个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>