Thymeleaf扩展

扩展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>