概述:Thymeleaf 3.0在Spring MVC中的新特性

Thymeleaf是一款用于处理和创建HTML、XML、JavaScript、CSS和纯文本的Java模板引擎。对于Thymeleaf和Spring的入门介绍,可以参考这篇文章:Thymeleaf与Spring集成

本文将探讨Thymeleaf 3.0在Spring MVC应用中新增的功能,包括自然处理和内联JavaScript。版本3引入了新的模板模式和底层改进。具体来说,我们将涉及纯文本、JavaScript和CSS模板处理的主题。

Thymeleaf 3.0包含三种新的文本模板模式:TEXTJAVASCRIPTCSS,分别用于处理纯文本、JavaScript和CSS模板。

1. Maven依赖

首先,让我们看看如何将Thymeleaf与Spring集成。在项目依赖中需要添加thymeleaf-spring库:

注意,对于Spring 4项目,应使用thymeleaf-spring4库,而不是thymeleaf-spring5。最新的依赖版本可以在这里找到

2. Java Thymeleaf配置

首先,我们需要配置新的模板引擎、视图解析器和模板解析器。为此,需要更新之前创建的Java配置类,如这里所示。除了新的解析器类型,我们的模板还需要实现Spring接口ApplicationContextAware

@Configuration
@EnableWebMvc
@ComponentScan({ "com.baeldung.thymeleaf" })
public class WebMVCConfig implements WebMvcConfigurer, ApplicationContextAware {

    private ApplicationContext applicationContext;

    // Java setter

    @Bean
    public ViewResolver htmlViewResolver() {
        ThymeleafViewResolver resolver = new ThymeleafViewResolver();
        resolver.setTemplateEngine(templateEngine(htmlTemplateResolver()));
        resolver.setContentType("text/html");
        resolver.setCharacterEncoding("UTF-8");
        resolver.setViewNames(ArrayUtil.array("*.html"));
        return resolver;
    }
    
    @Bean
    public ViewResolver javascriptViewResolver() {
        ThymeleafViewResolver resolver = new ThymeleafViewResolver();
        resolver.setTemplateEngine(templateEngine(javascriptTemplateResolver()));
        resolver.setContentType("application/javascript");
        resolver.setCharacterEncoding("UTF-8");
        resolver.setViewNames(ArrayUtil.array("*.js"));
        return resolver;
    }
    
    @Bean
    public ViewResolver plainViewResolver() {
        ThymeleafViewResolver resolver = new ThymeleafViewResolver();
        resolver.setTemplateEngine(templateEngine(plainTemplateResolver()));
        resolver.setContentType("text/plain");
        resolver.setCharacterEncoding("UTF-8");
        resolver.setViewNames(ArrayUtil.array("*.txt"));
        return resolver;
    }
}

如上所述,我们创建了三个不同的视图解析器,分别针对HTML视图、JavaScript文件和纯文本文件。Thymeleaf通过检查文件扩展名来区分它们:.html.js.txt

我们还创建了一个静态ArrayUtil类,以使用array()方法创建包含视图名称的字符串数组。

接下来,在该类的其余部分,我们需要配置模板引擎:

private ISpringTemplateEngine templateEngine(ITemplateResolver templateResolver) {
    SpringTemplateEngine engine = new SpringTemplateEngine();
    engine.setTemplateResolver(templateResolver);
    return engine;
}

最后,我们需要创建三个独立的模板解析器:

private ITemplateResolver htmlTemplateResolver() {
    SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
    resolver.setApplicationContext(applicationContext);
    resolver.setPrefix("/WEB-INF/views/");
    resolver.setCacheable(false);
    resolver.setTemplateMode(TemplateMode.HTML);
    return resolver;
}
    
private ITemplateResolver javascriptTemplateResolver() {
    SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
    resolver.setApplicationContext(applicationContext);
    resolver.setPrefix("/WEB-INF/js/");
    resolver.setCacheable(false);
    resolver.setTemplateMode(TemplateMode.JAVASCRIPT);
    return resolver;
}
    
private ITemplateResolver plainTemplateResolver() {
    SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
    resolver.setApplicationContext(applicationContext);
    resolver.setPrefix("/WEB-INF/txt/");
    resolver.setCacheable(false);
    resolver.setTemplateMode(TemplateMode.TEXT);
    return resolver;
}

请注意,为了便于测试,最好使用非缓存模板,因此推荐使用setCacheable(false)方法。

JavaScript模板将存储在/WEB-INF/js文件夹中,纯文本文件在/WEB-INF/txt文件夹中,而HTML文件的路径是/WEB-INF/html

3. Spring控制器配置

为了测试新配置,我们创建了一个Spring控制器:

@Controller
public class InliningController {

    @RequestMapping(value = "/html", method = RequestMethod.GET)
    public String getExampleHTML(Model model) {
        model.addAttribute("title", "Baeldung");
        model.addAttribute("description", "Thymeleaf tutorial");
        return "inliningExample.html";
    }
    
    @RequestMapping(value = "/js", method = RequestMethod.GET)
    public String getExampleJS(Model model) {
        model.addAttribute("students", StudentUtils.buildStudents());
        return "studentCheck.js";
    }
    
    @RequestMapping(value = "/plain", method = RequestMethod.GET)
    public String getExamplePlain(Model model) {
        model.addAttribute("username", SecurityContextHolder.getContext()
          .getAuthentication().getName());
        model.addAttribute("students", StudentUtils.buildStudents());
        return "studentsList.txt";
    }
}

在HTML示例中,我们将展示如何使用新内联功能,以及带有和不带HTML标签转义的情况。

对于JS示例,我们将生成一个AJAX请求,加载包含学生信息的js文件。请注意,我们在StudentUtils类的简单buildStudents()方法中使用了它,参见这篇文章

在纯文本示例中,我们将显示学生信息作为文本文件。使用纯文本模板模式的一个典型例子可能是发送纯文本电子邮件。

此外,我们将使用SecurityContextHolder获取已登录用户的用户名。

4. HTML/JS/Text示例文件

教程的最后部分是创建三种不同类型的文件,并测试Thymeleaf新特性的用法。让我们从HTML文件开始:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Inlining example</title>
</head>
<body>
    <p>Title of tutorial: [[${title}]]</p>
    <p>Description: [(${description})]</p>
</body>
</html>

在这个文件中,我们采用了两种不同的方法。为了显示标题,我们使用转义语法,这将移除所有HTML标签,只显示文本。描述部分使用未转义语法,保留HTML标签。最终效果如下:

<p>Title of tutorial: Baeldung</p>
<p>Description: <strong>Thymeleaf</strong> tutorial</p>

浏览器会解析这个内容,将单词Thymeleaf以粗体样式显示出来。

接下来,我们测试JavaScript模板特性:

var count = [[${students.size()}]];
alert("Number of students in group: " + count);

JAVASCRIPT模板模式中,属性将以JavaScript未转义的方式呈现。这将导致创建一个弹出警告。我们在listStudents.html文件中使用jQuery AJAX加载这个警告:

<script>
    $(document).ready(function() {
        $.ajax({
            url : "/spring-thymeleaf/js",
            });
        });
</script>

最后但同样重要的是,我们要测试纯文本文件生成。我们创建了一个名为studentsList.txt的文件,内容如下:

Dear [(${username})],

This is the list of our students:
[# th:each="s : ${students}"]
   - [(${s.name})]. ID: [(${s.id})]
[/]
Thanks,
The Baeldung University

与标记模板模式一样,标准方言仅包含一个可处理元素\[# ... \]和一组可处理属性(如th:textth:utextth:ifth:unlessth:each等)。结果将是一个文本文件,可用于例如电子邮件,如第3节末尾所述。

如何测试? 我们的建议是先在浏览器中尝试,然后检查现有的JUnit测试。

5. Thymeleaf在Spring Boot中的应用

Spring Boot通过添加spring-boot-starter-thymeleaf依赖提供了对Thymeleaf的自动配置:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
    <version>2.3.3.RELEASE</version>
</dependency>

无需显式配置。默认情况下,HTML文件应放在resources/templates目录下。

6. 结论

本文讨论了Thymeleaf框架在3.0版本中实现的新功能。完整实现可在GitHub项目中找到,这是一个基于Eclipse的项目,适合在现代浏览器中进行测试。

如果你计划从2.x版本迁移到最新版本,可以查看迁移指南。值得注意的是,你的现有Thymeleaf模板几乎与Thymeleaf 3.0完全兼容,只需在配置中做少许修改即可。