在springboot之外使用thymeleaf渲染text

thymeleaf是springboot默认的模版引擎,最近需要“渲染模版”这个功能,想到了thymeleaf,记一下怎么用。

依赖

        <!-- https://mvnrepository.com/artifact/org.thymeleaf/thymeleaf -->
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf</artifactId>
            <version>3.0.11.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>29.0-jre</version>
        </dependency>

代码

import java.util.HashMap;
import java.util.Map;

public final class RenderParam {
    private Map<String, Object> map = new HashMap<>();

    public Map<String, Object> getContent() {
        return map;
    }

    public RenderParam add(String key, Object value) {
        map.put(key, value);
        return this;
    }
}
package com.arloor.forwardproxy.util;

import com.arloor.forwardproxy.vo.RenderParam;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.StringTemplateResolver;

public class RenderUtil {
    private final static TemplateEngine textEngine = new TemplateEngine();
    private final static TemplateEngine htmlEngine = new TemplateEngine();

    static {
        StringTemplateResolver textResolver = new StringTemplateResolver();
        textResolver.setOrder(1);
        textResolver.setTemplateMode(TemplateMode.TEXT);
        // TODO Cacheable or Not ?
        textResolver.setCacheable(true);
        textEngine.setTemplateResolver(textResolver);

        StringTemplateResolver templateResolver = new StringTemplateResolver();
        templateResolver.setOrder(1);
        templateResolver.setTemplateMode(TemplateMode.HTML);
        // TODO Cacheable or Not ?
        templateResolver.setCacheable(true);
        htmlEngine.setTemplateResolver(templateResolver);
    }

    /**
     * 使用 Thymeleaf 渲染 Text模版
     * Text模版语法见:https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#textual-syntax
     *
     * @param template    模版
     * @param renderParam 参数
     * @return 渲染后的Text
     */
    public static String text(String template, RenderParam renderParam) {

        Context context = new Context();
        context.setVariables(renderParam.getContent());
        return textEngine.process(template, context);
    }

    /**
     * 使用 Thymeleaf 渲染 Html模版
     *
     * @param template    Html模版
     * @param renderParam 参数
     * @return 渲染后的html
     */
    public static String html(String template, RenderParam renderParam) {
        Context context = new Context();
        context.setVariables(renderParam.getContent());
        return htmlEngine.process(template, context);
    }

    /**
     * 测试用,展示如何使用
     *
     * @param args
     */
    public static void main(String[] args) {
        // 渲染String
        String string_template = "这是[(${name.toString()})]"; // 直接name其实就行了,这里就是展示能调用java对象的方法
        String value = RenderUtil.text(string_template, new RenderParam().add("name", "ARLOOR"));
        System.out.println(value);

        // 渲染List
        /**
         * [# th:each="item : ${items}"]
         *   - [(${item})]
         * [/]
         */
        String list_template = "[# th:each=\"item : ${items}\"]\n" +
                " - [(${item})]\n" +
                "[/]";
        String value1 = RenderUtil.text(list_template, new RenderParam().add("items", Lists.newArrayList("第一个", "第二个", "第三个")));
        System.out.println(value1);

        // 渲染Map
        /**
         * [# th:each="key : ${map.keySet()}"]
         *   - [(${map.get(key)})]
         * [/]
         */
        String map_template = "[# th:each=\"key : ${map.keySet()}\"]\n" +
                " - [(${map.get(key)})]\n" +
                "[/]";
        String value2 = RenderUtil.text(map_template, new RenderParam().add("map", ImmutableMap.of("a", "b", "c", "d")));
        System.out.println(value2);

        String html_template = "这是<span th:text=\"${name}\"></span>";
        System.out.println(RenderUtil.html(html_template, new RenderParam().add("name", "ARLOOR")));
    }
}

thymeleaf渲染非标记语言(没有tag)时,需要在外面包上自己的tag,例如:详情可见textual语法

[# th:each="item : ${items}"]
  - [(${item})]
/]

其他

如果是在Springboot应用中,有一个ThymeleafAutoConfiguration,如果thymeleaf的TemplateMode.class在classpath则会激活这个autoconfiguration。我们在最上面加入了thymeleaf的依赖,但是不是thymeleaf-springboot-starter这种包,会导致应用起不来。

解决方案,在@SpringBootApplication下加上:

@EnableAutoConfiguration(exclude={ThymeleafAutoConfiguration.class})

或者引入thymeleaf的springboot-starter包