SpringBoot整合thymeleaf

SpringBoot整合thymeleaf

1.Thymeleaf 简介

1.1 概述

Thymeleaf 是一个跟 VelocityFreeMarker 类似的模板引擎,它可以完全替代 JSP 。相较与其他的模板引擎,它有如下三个极吸引人的特点

  • Thymeleaf 在有网络和无网络的环境下皆可运行,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果。这是由于它支持 html 原型,然后在 html 标签里增加额外的属性来达到模板 + 数据的展示方式。浏览器解释 html 时会忽略未定义的标签属性,所以 thymeleaf 的模板可以静态地运行;当有数据返回到页面时,Thymeleaf 标签会动态地替换掉静态内容,使页面动态显示。
  • Thymeleaf 开箱即用的特性。它提供标准和 Spring 标准两种方言,可以直接套用模板实现 JSTL、 OGNL 表达式效果,避免每天套模板、改 JSTL、改标签的困扰。同时开发人员也可以扩展和创建自定义的方言。
  • Thymeleaf 提供 Spring 标准方言和一个与 SpringMVC 完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能。

2. 为什么使用 Thymeleaf

如果希望以 Jar 形式发布模块则尽量不要使用 JSP 相关知识,这是因为 JSP 在内嵌的 Servlet 容器上运行有一些问题 (内嵌 TomcatJetty 不支持 Jar形式运行 JSPUndertow 不支持 JSP)。

Spring Boot 中推荐使用 Thymeleaf 作为模板引擎,因为 Thymeleaf 提供了完美的 Spring MVC 支持

Spring Boot 提供了大量模板引擎,包括:

  • FreeMarker
  • Groovy
  • Mustache
  • Thymeleaf
  • Velocity
  • Beetl

3. 第一个 Thymeleaf 模板页

3.1 引入依赖

主要增加 spring-boot-starter-thymeleafnekohtml 这两个依赖

  • spring-boot-starter-thymeleafThymeleaf 自动配置
  • nekohtml:允许使用非严格的 HTML 语法

3.2 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.zysheep</groupId>
    <artifactId>spring-boot-thymeleaf</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-boot-thymeleaf</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>


        <dependency>
            <groupId>net.sourceforge.nekohtml</groupId>
            <artifactId>nekohtml</artifactId>
            <version>1.9.22</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

3.3 在 application.yml 中配置 Thymeleaf

###ThymeLeaf配置
spring:
  thymeleaf:
    cache: false # 开发时关闭缓存,不然没法看到实时页面
    #模板的模式,支持 HTML, XML TEXT JAVASCRIPT
    mode: HTML5 # 用非严格的 HTML
    #编码 可不用配置
    encoding: UTF-8
    #内容类别,可不用配置
    servlet:
      content-type: text/html 
#Tomcat 服务
server:
  port: 80

3.4 创建测试用 JavaBean

创建一个测试效果的 JavaBean,简单封装一下即可

public class User implements Serializable {
    private String username;
    private Integer age;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

3.5 创建测试用 Controller

创建一个 Controller,造一些测试数据并设置跳转

@Controller
public class MainController {

    @RequestMapping(value = {"/","thymeleaf/index"},method = RequestMethod.GET)
    public String index(Model model){
        User user = new User();
        user.setUsername("zysheep");
        user.setAge(20);
        model.addAttribute("user",user);

        return "index";
    }
}

3.6 创建测试页面

templates 目录下创建 index.html 文件,代码如下:

<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<html >
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<span th:text="${user.username}">小明</span>
</body>
</html>

修改 html 标签用于引入 thymeleaf 引擎,这样才可以在其他标签里使用 th:* 语法,声明如下:

<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">

3.7 测试访问

启动成功后,访问:http://localhost/thymeleaf/index 即可看到效果 SpringBoot整合thymeleaf

4 语法

4.1 标签使用

th:text 基础信息输出

HTML代码:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>th:text</title>
</head>
<body>

<span th:text="${user.username}">小明</span>
</body>
</html>

Java代码:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
    private String username;
    private Integer age;

}
@Controller
public class ThyymeleafController {

    /**
     * @param  Model model
     * @return  String
     * @author Administrator
     * @throws
     * @date 2020/3/18 10:59
     */
    @GetMapping("/")
    public String index(Model model){
        User user = new User();
        user.setUsername("伽罗");
        user.setAge(21);
        model.addAttribute("user",user);

        return "th-text";
    }

}

th:utext html内容输出

使用"th:text"是对内容的原样输出,使用“th:utext”可以进行html标签输出。

Java代码:

@RequestMapping("/eat")
public ModelAndView eat() {
    ModelAndView modelAndView = new ModelAndView("/cat");
    modelAndView.addObject("data", "<span style='color:red'>老王是吃货</span>");
    return modelAndView;
}

HTML代码:

<h4 th:text="'th:text '+${data}"></h4>
<h4 th:utext="'th:utext '+${data}"></h4>

th:if, th:unless 条件判断

th:if为满足条件的业务处理,th:unless正好相反,是除去的意思。

<span th:if="${age > 18}">
    成年
</span>
<span th:unless="${age > 18}">
    未成年
</span>

th:switch, th:case 多条件判断

<div th:switch="${age}">
    <span th:case="18">18岁</span>
    <span th:case="19">19岁</span>
    <spa th:case="*">其他</spa>
</div>

注意 :默认选项使用th:case="*" 指定。

th:each 循环

<div th:each="name,item:${names}">
    <span th:text="${item.count}"></span>
    <span th:text="${name}"></span>
</div>
@RequestMapping("/")
public ModelAndView index() {
    ArrayList<String> names = new ArrayList<>();
    names.add("java");
    names.add("golang");
    names.add("nodejs");
    ModelAndView modelAndView = new ModelAndView("/index"); 
    modelAndView.addObject("names",names);
    return modelAndView;
}

其中item为每行的详细值,key值如下:

  • index 下标,从0开始
  • count 第x个,从1开始
  • size 这个集合的大小
  • current 当前行的值

th:fragment、th:insert、th:replace、th:include 代码片段复用

  • th:fragment标签是声明代码片段,用于解决代码复用的问题,好比Java程序写的公用代码一样,每个需要的地方都可以直接调用;
  • th:insert 引用fragment的代码,保留自己的主标签;
  • th:replace 引用fragment的代码,不保留自己的主标签;
  • th:include 使用类似th:replace,Thymeleaf3.0之后不推荐使用;

footer.html页面代码:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
</head>
<body>

<div th:fragment="copyright">
    © 著作权归 老王 所有
</div>

<div th:fragment="about">
    关于
</div>

<div th:fragment="links">
    CCTV
</div>

</body>
</html>

声明了两个代码片段,copyrightabout

cat.html页面代码:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
</head>
<body>
<div th:replace="footer :: copyright"></div>

<div th:insert="footer :: about"></div>

<div th:include="footer :: links"></div>
</body>
</html>

其中第一个div引用了footer.html 的 copyright 代码片段,第二个div引用了 footer.html 的 about 代码片段。

双冒号的理解: 其中使用“::”双冒号来完成对页面片段的引用,有点像php里面的语法,使用双冒号来表示对类的静态属性和方法进行直接引用。

总结: 可以很清晰的看出th:insertth:replaceth:include之间的区别,在于是否保留自己的主标签,th:include 在3.0之后已经不推荐使用了,可以使用th:replace标签替代。

fragment代码传参

使用fragment我们是可以在html代码中传参的,比如我们定义了一个top.html其中有一个“欢迎XXX”的提示,而这个人名XXX就是需要动态传递的,这样我们可以最大程度的完成代码的复用,这个时候就是一个很好的使用场景,我们需要这样做。

页面main.html代码:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org"
>
<head>
    <meta charset="UTF-8">
</head>
<body>

<div th:replace="footer :: webcome('老王')"></div>

</body>
</html>

页面top.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org"
>
<head>
    <meta charset="UTF-8">
</head>
<body>

<div th:fragment="webcome(about)">
    <span th:text="'欢迎:'+${about}"></span>
</div>

</body>
</html>

th:with 定义局部变量

页面代码:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org"
>
<head>
    <meta charset="UTF-8">
</head>
<body>
<div th:with="sum=4-2">
    <span th:text="${sum}"></span>
</div>
</body>
</html>

页面输出结果:2

th:remove 删除标签

th:remove用于html代码的删除,th:remove值有五个:

  • all 删除本段所有代码
  • body 删除主标签内的所有元素
  • tag 删除主标签,保留主标签所有的元素
  • all-but-first 保留主标签和第一个元素,其他全部删除
  • none 不删除任何标签

其他标签

  • th:style 定义样式

  • th:onclick 点击事件

  • th:href 赋值属性href

  • th:value 赋值属性value

  • th:src 赋值src

  • th:action 赋值属性action

  • th:id 赋值属性id

  • th:attr 定义多个属性

  • th:object 定义一个对象

  • th:field 表单字段绑定。

  • th:href 定义超链接。

  • th:id div 标签中的ID 声明,类似HTML 标签中的归属性。

  • th:if 条件判断语句。

  • th:include 布局标签,替换内容到引入文件。

4.2 表达式使用

4.2.1 简单表达式

  • 变量表达式:${…}
  • 选择变量表达式:*{…}
  • 消息表达式:#{…}
  • 链接表达式:@{…}
  • 片段表达:~{…}

4.2.2 数据的类型

  • 文字:‘one text’, ‘Another one!’,…
  • 数字文字:0, 34, 3.0, 12.3,…
  • 布尔文字:true, false
  • NULL文字:null
  • 文字标记:one, sometext, main,…

4.2.3. 文本操作

  • 字符串拼接:+
  • 字面替换:|The name is ${name}|

4.2.4 算术运算

  • 二进制运算符:+, -, *, /, %
  • 减号(一元运算符):-

4.2.5 布尔运算

  • 二进制运算符:and, or
  • 布尔否定(一元运算符):!, false

4.2.6 条件运算符

  • 比较值:>, <, >=, <=
  • 相等判断: ==, !=

4.2.7 条件判断

  • 如果-然后:(if) ? (then)
  • 如果-然后-否则:(if) ? (then) : (else)
  • 违约:(value) ?: (defaultvalue)

4.3 表达式使用实例

4.3.1 变量表达式 ${…}

变量表达式的使用,我们前面的代码已经见到了,``是我们平常开发中最常用的表达式,用于把后台Java类的动态数据,映射到页面,例如:

Java代码:

public ModelAndView index() {
    ModelAndView modelAndView = new ModelAndView("/cat");
    modelAndView.addObject("data", "hello world!");
    return modelAndView;
}

HTML代码:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
</head>
<body>
<span th:text="${data}"></span>
</body>
</html>

4.3.2 选择表达式 *{…}

选择表达式相当于选择了一个对象,在使用的时候不在需要这个对象的前缀,直接使用属性的key进行内容展示,代码如下:

<div th:object="${user}">
    <span th:text="${user.username}"></span>
    <span th:text="*{age}"></span>
    <span th:text="${#dates.format(user.createTime, 'yyyy-MM-dd HH:mm:ss')}"></span>
</div>

最终效果:

伽罗 21 2020-03-18 14:09:22

总结 : *{age} = ${user.age}只是省去了“user.”前缀,效果都是一样的。

4.3.3 链接表达式 @{…}

用于转换url,代码如下:

<a th:href="@{/footer(id=666,name=laowang)}">链接</a>

最终呈现的效果:

<a href="/footer?id=666&name=laowang">链接</a>

链接表达式,可以传递参数,用逗号分隔。服务器根相对路径:@{~/path/to/something}

4.3.4 文本操作

文本操作分为两个:文本拼加、文本替换

文本拼加 :

<span th:text="'我叫'+${name}"></span>

文本替换 : 文本替换的语法:|内容${tag}|

<span th:text="|我叫${name},是一名开发工程师。|"></span>

4.3.5 三元表达式

<tr th:class="${row.even}? 'even' : 'odd'">

4.3.6 双括号作用

<p th:text="${val}">...</p>

结果:

<p>1234567890</p>
<p>1,234,567,890</p>

4.3.7 嵌入文本标签

虽然标准的标签几乎可以满足所有的业务场景,但某些情况我们更喜欢直接写入HTML文本,例如:

<p>Hello, [[${name}]]</p>

嵌入文本有两种写法“[[…]]”和“[(…)]”,分别的作用就像th:text 和 th:utext 一样,例如:

<p>
    [[${name}]]
</p>
<p>
    [(${name})]
</p>

4.4 表达式对象概述

4.4.1 表达式基本对象

#ctx: 操作当前上下文.
#vars: 操作上下文变量.
#request: (仅适用于Web项目) HttpServletRequest对象.
#response: (仅适用于Web项目) HttpServletResponse 对象.
#session: (仅适用于Web项目) HttpSession 对象.
#servletContext: (仅适用于Web项目) ServletContext 对象.

4.4.2 表达式实用工具类

 #execInfo: 操作模板的工具类,包含了一些模板信息,比如:${#execInfo.templateName} .
 #uris: url处理的工具
 #conversions: methods for executing the configured conversion service (if any).
 #dates: 方法来源于 java.util.Date 对象,用于处理时间,比如:格式化.
 #calendars: 类似于 #dates, 但是来自于 java.util.Calendar 对象.
 #numbers: 用于格式化数字.
 #strings: methods for String objects: contains, startsWith, prepending/appending, etc.
 #objects: 普通的object对象方法.
 #bools: 判断bool类型的工具.
 #arrays: 数组操作工具.
 #lists: 列表操作数据.
 #sets: Set操作工具.
 #maps: Map操作工具.
 #aggregates: 操作数组或集合的工具.
 #dates 日期函数。
 #lists 列表函数。
 #arrays 数组函数。
 #strings 字符串函数。
 #numbers 幸生字函捷生。
 #ca lendars 日历函数。
 #objects 对象函数。
 #bools 逻辑函数。

5. Thymeleaf引用静态资源

Spring BootThymeleaf结构模块很好提供了静态资源的引用方法

th:[href | src]@{资源在static下的目录}, 如:@{lib/jquery.js},不用填写默认的static文件夹

案例

  1. 资源目录结构 SpringBoot整合thymeleaf
  2. templates目录下的ws.html可以这样引用static下的资源文件
<!DOCTYPE html>
<html lang="en" xmlns:th="https://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>xxx</title>
    <link rel="stylesheet" type="text/css" th:href="@{css/ws.css}"/>
</head>
<body>

<!-- 导入库 -->
<script th:src="@{lib/sockjs.min.js}"></script>
<script th:src="@{lib/stomp.min.js}"></script>
<script th:src="@{lib/jquery.js}"></script>
<script th:src="@{js/ws.js}"></script>
</body>
</html>

使用原始的相对路径的话,则为 href="…/static/css/ws.css", src="…/static/lib/jquery.js" 注意:使用Thymeleaf的引用方法,只有运行项目才有效。普通打开HTML无法解析。

上一篇:“杀死”线程


下一篇:springboot整合Thymeleaf模板