强大的模版引擎 Thymeleaf

376 阅读5分钟

1. 引言

说明模版引擎,大家想必不会陌生,首先想到的就是JSP了。说起来,JSP模版引擎几乎陪伴了我从java Web从小白到熟悉的整个过程,各种标签可以说是如数家珍。但最近在用Spring Boot整项目的时候,实在无力吐槽了,本身Spring Boot并不支持JSP模版引擎,所以自己非要支持,这就很难受了。不得已而为之,只能使用Spring Boot

推荐的模版引擎之一Thymeleaf。不用不知道,一用真是感觉very nice!废话不多说,开始介绍。

2. Thymeleaf 介绍

要想了解Thymeleaf,必须官网走一波:www.thymeleaf.org/

目前最新稳定版本是Thymeleaf 3.0.11

官网上介绍就是各种NB,各种Nice,总结几点就是:

  • Thymeleaf是用来开发Web和独立环境项目的服务器端的Java模版引擎
  • hymeleaf与SpringMVC的视图技术,及SpringBoot的自动化配置集成非常完美,几乎没有任何成本,你只用关注Thymeleaf的语法即可。

自己在一开始接触认为最大的特点:

  • Thymeleaf是html模型,它比JSP最大的优点就是不会破坏原html页面,也就是说我们可以不破坏美工设计的页面,就可以写入我们的功能。

总结了网络上大家的认为id特点:

  • 动静结合:Thymeleaf 在有网络和无网络的环境下皆可运行,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果。这是由于它支持 html 原型,然后在 html 标签里增加额外的属性来达到模板+数据的展示方式。浏览器解释 html 时会忽略未定义的标签属性,所以 thymeleaf 的模板可以静态地运行;当有数据返回到页面时,Thymeleaf 标签会动态地替换掉静态内容,使页面动态显示。
  • 开箱即用:它提供标准和spring标准两种方言,可以直接套用模板实现JSTL、 OGNL表达式效果,避免每天套模板、该jstl、改标签的困扰。同时开发人员也可以扩展和创建自定义的方言。
  • 多方言支持:Thymeleaf 提供spring标准方言和一个与 SpringMVC 完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能。
  • 与SpringBoot完美整合,SpringBoot提供了Thymeleaf的默认配置,并且为Thymeleaf设置了视图解析器,我们可以像以前操作jsp一样来操作Thymeleaf。代码几乎没有任何区别,就是在模板语法上有区别。

3. Spring Boot引入Thymeleaf

首先创建一个Spring Boot项目(使用的版本是Spring Boot 2.2.1),添加相关依赖

pom.xml

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
       <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
 </dependencies>

Spring Boot自动配置已经有Thymeleaf的自动配置,只有当你引入依赖之后,这些配置才会自动生效!

我们可以查看一些Thymeleaf的自动配置中已经给我们定义了读取模版文件的前缀名(位置)以及后缀名

@ConfigurationProperties(
    prefix = "spring.thymeleaf"
)
public class ThymeleafProperties {
    private static final Charset DEFAULT_ENCODING;
    public static final String DEFAULT_PREFIX = "classpath:/templates/";
    public static final String DEFAULT_SUFFIX = ".html";
    private boolean checkTemplate = true;
    private boolean checkTemplateLocation = true;
    private String prefix = "classpath:/templates/";
    private String suffix = ".html";
    private String mode = "HTML";

4. 测试实例

手写一个Controller:演示一下获取request域、session域以及ServletContext域中的内容

@Controller
public class DemoContoller {
    @Autowired
    private HttpSession session;
    @Autowired
    private ServletContext application;
    @GetMapping("/test01")
    public String m1(Model model){
        model.addAttribute("userName","三国演义");
        session.setAttribute("author","罗贯中");
        application.setAttribute("createDate",new Date());
        return "demo01";
    }
}

将返回的对应的模版添加到默认的位置下:

这里可以演示出Thymeleaf的动静结合的好处:

比如我的demo01是这样定义的:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"> //注意必须引入,否则没有提示
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1 th:text="${userName}">西游记</h1>
</body>
</html>

如果是一个静态的文件打开显示的是西游记:

如果是Thymeleaf模版文件:

演示完,就来获取一波数据,demo01.html:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
   <!-- <h1 th:text="${userName}">西游记</h1>-->
    <h2>request的获取方式</h2>
    <h1 th:text="${userName}+','+${userName}" ></h1>
    <h1 th:text="|${#request.getAttribute('userName')},${#request.getAttribute('userName')}|" ></h1>
    <h2>session的获取方式</h2>
    <span th:text="|${session.author},${session['author']},${#httpSession.getAttribute('author')}|"></span>
    <h2>application的获取方式</h2>
    <span th:text="${application.createDate}"></span>
    <span th:text="${#servletContext.getAttribute('createDate')}"></span>
    <span th:text="${application['createDate']}"></span>
</body>
</html>

5.Thymeleaf 常用用法

如上面可以使用一些基本的标签获取数据,这里要提醒的是大家不要意味${}是EL表达式,而是ognl表达式,两者用法非常像!常用用法:

  1. 对上面从ServletContext中取到的日期进行格式化
<input type="text" th:value="${#dates.format(application.createDate)}">
  1. 操作对象

Entity:

public class User {
    private  Integer userId;
    private  String userName;
    private  Integer userAge;
    private  Integer userSex;
    private  String[] hobbyArray;
    public Integer getUserId() {
        return userId;
    }
    public void setUserId(Integer userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public Integer getUserAge() {
        return userAge;
    }
    public void setUserAge(Integer userAge) {
        this.userAge = userAge;
    }
    public Integer getUserSex() {
        return userSex;
    }

    public void setUserSex(Integer userSex) {
        this.userSex = userSex;
    }
    public String[] getHobbyArray() {
        return hobbyArray;
    }
    public void setHobbyArray(String[] hobbyArray) {
        this.hobbyArray = hobbyArray;
    }
}

Controller:

@GetMapping("/test02")
    public String m2(Model model){
        User user=new User();
        user.setUserId(999);
        user.setUserName("悟空");
        user.setUserAge(50);
        user.setUserSex(1);
        user.setHobbyArray(new String[]{"篮球","足球","音乐"});
        model.addAttribute("user",user);
        return "demo02";
    }

Thymeleaf模版页面:

<h1>显示数据的方式</h1>
    <ul>
        <li th:text="${user.userName}"></li>
        //单选框的选择上
        <li th:if="${user.userSex==1}">男生</li>
        <li th:unless="${user.userSex==1}">女生</li>
    </ul>
    <ol th:object="${user}">
        <li th:text="*{userName}"></li>
        <li th:if="*{userSex==1}">男生</li>
        <li th:unless="*{userSex==1}">女生</li>
    </ol>
    <select name="" id="">
    	//遍历
        <option value="" th:each="hobby,vs:${user.hobbyArray}" th:value="|${vs.index},${vs.count}|" th:text="${hobby}"></option>
    </select>
    <h1>[[${user.userName}]]</h1> 
    //javascript取数据
    <script>
        var name='[[${user.userName}]],[[${user.userSex}]]'
        alert(name);
    </script>
  1. 其他用法

其他用法用到的时候自行查阅,一般直接看官网文档就可以的!