Thymeleaf基本用法

11-Thymeleaf

简单介绍

Thymeleaf是一个模板引擎,采用Java开发。

Thymeleaf对网络环境要求不严格,既能用于Web环境,也能用于非Web环境。在非Web环境(即不开启服务器,只打开该文件)下,可以直接显示模板的静态数据;在Web环境下,可以像JSP一样从后台接受数据,并替换掉模板的静态数据,它是基于HTML的,以HTML为载体,Thymeleaf要寄托在HTML标签下才可以实现。

SpringBoot集成了Thymeleaf技术,SpringBoot官方也推荐使用Thymeleaf来代替JSP技术。但它本身并不属于SpringBoot。

该模板文件可以直接在任何浏览器内正确显示,浏览器会自动忽略不能理解的属性。但是这并不是一个真正有效的HTML5文档,因为HTML5文档没有th:*这些非标准属性的。需要Thymeleaf解析后才会变成一个标准的HTML文档。

Thymeleaf的简单使用

首先要加入Thymeleaf的起步依赖,可以在创建SpringBoot项目时就直接添加该依赖。

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

然后创建html文件,并且需要在文件中添加:

<html xmlns:th="http://www.thymeleaf.org">

即html文件变成:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

</body>
</html>

并且默认将该模板文件放在resources/templates目录中,将其他静态资源文件如js,css,图片等放在resources/static目录中。

Thymeleaf基础语法

所有有关Thymeleaf的属性开头都是th:**代表任意属性。有些浏览器不支持该写法。也可以使用data-th-*来代替th:*语法。

显示文本

使用th:textth:utext来显示数据。

两者不同是:

th:text属性不解析html元素,传来什么数据就显示什么数据。

th:utext属性将解析HTML元素。如传来的数据是<p>一个段落</p>,那么该属性会识别到

是一个html标签,进行解析。

简单表达式

语法 描述 作用
${..} 变量表达式 取出上下文变量的值
*{..} 选择变量表达式 取出选择的对象的属性值
#{..} 消息表达式 能够从外部源(.properties文件)获得属性值,一般用于国际化消息
@{..} 链接表达式 用于表示各种超链接地址
~{..} 片段表达式 引用一段公共的代码片段

变量表达式

语法:${变量名}

说明:标准变量表达式用于访问容器上下文环境的变量。Thymeleaf使用变量表达式来获取Controller传过来的Model中的数据。

可以是简单变量String,Integer,这时候直接使用变量名即可。

也可以是引用变量,这时候要使用${变量名.属性名}的方式。

${..}的作用域是面向整个上下文。

一个例子:

控制器方法:

    @RequestMapping("/thymeleaf")
    public String getIndex(Model model) {
        User user = new User();
        user.setId(1);
        user.setName("张三");
        user.setAddress("河北省石家庄市");
        model.addAttribute("data", "测试Thymeleaf成功");
        model.addAttribute("user", user);
        return "index";
    }

html文件:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Thymeleaf</title>
</head>
<body>
    <p th:text="${data}"></p><br>
    用户的ID是:<span th:text="${user.id}"></span><br>
    用户的姓名是:<span th:text="${user.name}"></span><br>
    用户的地址是:<span th:text="${user.address}"></span><br>

</body>
</html>

运行结果:
image-20210123193016754

选择变量表达式

不推荐使用。

语法:*{...}

说明:也叫星号变量表达式。使用th:object属性来绑定对象。

然后使用*来代表这个对象,*后面的{}中的值时此对象的属性。

选择变量表达式*{..}类似于标准变量表达式${..}表示变量的写法。

选择变量表达式是在执行时在选择的对象上求解,而标准变量表达式是在上下文的Model上求解。

这种写法比较繁琐,不推荐使用。

选择变量表达式*{..}的作用域是父标签th:object

例子:

控制器方法不用改,html文件改为:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Thymeleaf</title>
</head>
<body>
    <h2 th:text="*{data}"></h2>
    <div th:object="${user}">
        用户ID:<span th:text="*{id}"></span>
        用户姓名:<span th:text="*{name}"></span>
        用户地址:<span th:text="*{getAddress()}"></span>
    </div>
</body>
</html>

也可以不使用th:object绑定对象,直接使用*{变量名.属性名},和${}用法一样。

消息表达式

消息表达式#{..}用于国际化文字信息,也就是根据语言改变显示文字,.properteis文件命名规则一般是:

  • basename.properties
  • basename_language.properties
  • basename_language_country.properties

其中:basename是自定义的资源文件名称,language和country是Java支持的语言和国家。如中国中文是messages_zn_CN.properties

basename.properties是缺省加载的资源文件,当客户端根据本地语言查找不到相关资源文件,则使用该配置文件。

资源文件应该放在resources目录中。

SpringBoot加载资源文件的默认名称是messages。并且默认放在resources目录中。如果放在其他目录或者名称不是messages,那么在application.properties中修改spring.messages.basename属性来修改。如放在resources/i18n目录中,basename是message,那么属性应变为spring.messages.basebame=i18n/message

一个例子

创建一个资源文件文件名为messages_zn_CH.properties

welcome.message=欢迎你!

在html文件中:

    <p th:text="#{welcome.message}"></p>

这样就可以调用到属性值。

使用占位符

消息表达式#{..}不允许直接处理费静态文本消息,例如调用变量。但是可以在资源文件中使用占位符{}来处理费静态文本消息:

资源文件配置:

welcome.message={0}, 欢迎你!
encoding={0}

然后在html中以参数形式传递变量:

    <p th:text="#{welcome.message('Jack')}"></p><br>
    字符编码是:<span th:text="#{encoding(${#request.getCharacterEncoding()})}"></span>

如果一个属性中有多个占位符,如encoding={0} {1},那么在参数传递时,使用逗号,来分割不同参数。

即:<span th:text="#{encoding('字符编码是:',${#request.getCharacterEncoding()})}"></span>

链接表达式

语法:@{..}

说明:主要用于链接地址的展示,适用的标签有<script src=""><a href=""><form action=""><img src="">等。可以在URL中动态获取路径,适用+连接字符串作为URL。

一个例子:

控制器方法

    @RequestMapping("/thymeleaf")
    public String getIndex(HttpServletRequest req, Model model) {
        model.addAttribute("contextPath", req.getContextPath());
        return "index";
    }

    @RequestMapping("/hello")
    public @ResponseBody String sayHello() {
        return "Hello!";
    }

html文件:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Thymeleaf</title>
</head>
<body>
    <a th:href="@{${contextPath} + '/hello'}">一个链接</a>
</body>

</html>

在标签a中使用th:href属性代替原来的href属性。并使用@{}来动态获取路径。

片段表达式

片段表达式~{..}可以用来引用一段公共的HTML的代码片段。

有三种用法:

  • ~{templatename}:引用整个模板文件的代码片段
  • ~{templatename::selector}:selector可以是th:fragment指定的名称或其他选择器,如ID选择器,类选择器
  • ~{::selector}:相当于~{this::selctor},表示引用当前模板定义的代码片段

在Thymeleaf模板文件中,使用th:fragment定义一段公共的代码片段:

在base.html文件中定义:

<div id="footer" th:fragment="footerFragment">重复代码片段</div>

再在另一文件中,通过th:insert属性引用一段公共的代码片段:

<div th:insert="~{base :: footerFragmemnt}"></div>

其中,~{}是可选的,可以去掉,变成

<div th:insert="base :: footerFragmemnt"></div>

如果两个文件不再同一级目录,那么就要在引用文件名加上目录。

也可以使用类选择器,ID选择器来引用公共代码片段。

ID选择器语法格式:文件名:#ID值

类选择器语法格式:文件名:.类值

加上参数

使用th:fragment属性定义代码片段时,还可以声明一组参数:

<div th:fragment="frag(param1,param2)">
    <i th:text="${param1}"></i><i th:text="${param2}"></i>
</div>

然后在调用时需要给这两个参数赋值,

<div th:insert="::frag('参数1', '参数2')"></div>

例如:

在base.html文件中定义代码片段:

    <div th:fragment="frag(param1, param2)">
        <h3 th:text="${param1}"></h3><br>
        <h3 th:text="${param2}"></h3><br>
    </div>

在同级目录中引用:

    <div th:insert="~{base::frag('参数1', '参数2')}"></div>
使用th:replace

除了th:insert属性,th:replace也可以来引用公共代码段。不同的是,th:insert直接将代码片段插入到标签体内,而th:replace则是代码片段直接替换标签体内容。

例如:在base.html文件中定义代码片段

<div th:fragment="frag">这是一个代码片段</div>

在同级目录文件中引用:

    <div th:insert="base::frag" style="color: red"></div>
    <div th:replace="base::frag" style="color: red"></div>

th:insert会把代码片段放在该属性所在的

标签里面,而th:replace则会替换该标签。

所以第一个代码片段文字是红的,第二个不是。

image-20210125160747573

内置对象

对象 描述
#ctx 上下文对象
#vars 同#ctx,表示上下文变量
#locale 上下文本地化变量,参考Locale类
#request HttpServletRequest对象
#response HttpServletResponse对象
#session HttpSession对象
#servletContext ServletContext对象

使用方法是在变量表达式中调用内置对象:

${内置对象}。如${#request.getParameter()}

除此之外,还有一个内置对象,param表示请求该页面时所携带的参数,不需要加符号#。例如:

URL为:http://lcoalhost/thymeleaf?id=1

该请求返回一个index.html页面。该页面使用th:text="${param.id}"即可取到参数。

同理,还有一个session内置对象,放入session的属性应该使用该内置对象拿到。和param使用方法一样。不要加#

工具类

Thymeleaf提供了相关工具类来处理参数:

对象 描述
#messages 消息工具类,和#{...}作用相同
#urls 地址相关工具类
#conversions 对象转换工具类
#dates 日期时间工具类
#calendars 日历工具类
#numbers 数字工具类
#strings 字符串工具类
#objects 对象工具类
#bools 布尔工具类
#arrays 数组工具类
#lists List集合工具类
#sets Set集合工具类
#maps Map集合工具类

字面值

字面值,其实就是常量的意思。通常这些值比较简单。

文字字面值

使用单引号''括起来的任何字符,如果字符内容里有单引号,则需要使用\进行转义。

数字字面值

直接写数字就可以,不需要其他符。

布尔字面值

直接写false或true即可。

空字面值

使用null。

字面令牌

字面令牌只能含有:

  • 大写或小写字母,中文等不含空格和特殊符号的文本
  • 0-9的数字
  • 中括号
  • 下划线_
  • 连字符-
  • 点符号.

字面令牌不能包含空格和特殊符号。

使用字面令牌能够对标准表达式语法进行简化。数字、布尔、空字面值其实都是字面令牌的特殊情况。

文本操作

可以对文本内容进行两种常用操作,字符串连接和替换。

字符串连接

不管是常量还是表达式结果,都可以使用+连接起来。

<p th:text="'Welcome to ' + ${location}">

字符串替换

符号||可以将字面值和表达式包括起来,这样就可以方便替换变量的值,不需要使用+连接符。

<p th:text="|Welcome to ${location}|">

运算符

Thymeleaf支持大多数运算。

算术运算符 含义
+
-
*
/
% 模(取余)
布尔运算符 含义
and 并,且运算
or 或运算
!
not
比较运算符 含义
< 小于,lt
> 大于,gt
<= 小于等于,le
>= 大于等于,ge
== 等于,eq
!= 不等于,ne
条件运算符 含义
(if) ? (then) : else 三元运算符,if表达式成立,则是then值,否则是else
(value) ?: (defaultValue) value非空(null)即真,条件为真输出value,否则输出defaultValue

还有一种:无操作符。

当模板运行在服务器端,Thymeleaf会解析th:*的属性具体值来替换标签体内容,无操作符_则会使用原型标签体内容作为默认值。

例如:<p th:text="${data} ?: _">数据为空</p>,表示当data变量为空,使用原数据,即数据为空,否则就显示data变量值。

设置属性值

在Thymeleaf中,使用th:*(*代表任意属性)或th:attr来设置任意HTML标签属性的值。

不仅如此,还可以使用th:*-*来同时为多个不同标签属性设置相同的一个值。甚至使用th:attrappendth:attrprepend来追加新的值到现有标签属性值中。

大部分都和HTML的属性一致,只不过加了th:。例如表单的action和method等属性。都可以加个th:。加了th:就可以使用Thymeleaf的表达式等内容。

th:attr

这种方式不推荐使用。了解一下就可以。

例子:使用th:attr="href=..."来设置标签href属性的值:

<a th:attr="href=@{http://www.google.com.hk}">谷歌一下</a>

th:*

推荐使用这种方式。显然前面哪种方式不够简洁。

<a th:href="@{http://www.google.com.hk}">谷歌一下</a>

这种更简单一些。

th:*-*

如果想同时为标签多个不同属性设置相同的一个值,可以使用th:*-*语法。

例如:

<img src="logo.png" th:alt-title="LOGO图片">

相当于:

<img src="logo.png" th:alt="LOGO图片" th-title="LOGO图片">

th:attrappend & th:attrprepend

th:attrappendth:attrprepend可以将表达式结果分别追加到指定属性值之后和之前

如:

<img src="logo.png" th:alt="LOGO图片" th-title="LOGO图片" th:attrappend="style='width:30px'">

此外,还有两个常用的具体附加属性:th:classappend="..."th:styleappend="..."。分别用来代替:

th:attrappend="class=..."th:attrappend="style=..."

如:<input type="text" th:styleappend="'color:red'" th:value="Hello">

注意:th:styleappend=""的值需要使用单引号全括起来。多个style属性使用的;也要在单引号里。

例如:th:styleappend="'color:red;font-size:30px'"

布尔属性

在HTML中有些是布尔属性,是指没有值的属性。如readonlycheckedselected等。它们存在则意味着值为true。

Thymeleaf允许使用th:*来选择是否使用这些布尔属性。如th:selectedth:checkedth:readonly

将该属性设为true和直接写一样。

遍历

遍历语法是:th:each="自定义元素变量名称 : ${集合变量名称}"

其中:

  • 自定义元素变量名称用于表示每次迭代的元素,即集合中的一个元素
  • 集合变量名称就是服务端传来的变量

并且,属性th:each还提供了一个用于跟踪迭代的状态变量,有以下几个属性:

  • index:int类型,当前迭代的索引,从0开始
  • count:int类型,当前迭代的计数,从1开始,就是索引+1。
  • size:int类型,集合元素个数
  • current:Object类型,就是元素类型,当前元素对象
  • even:Boolean类型,当前迭代计数count是否为偶数
  • odd:Boolean类型,当前迭代的计数count是否为奇数
  • first:Boolean类型,当前元素是否是集合第一个元素
  • last:Boolean类型,当前元素是否为集合最后一个元素

加上状态变量,则使用th:each的语法是:th:each="自定义元素变量名称, 自定义状态变量名称 : ${集合变量名称}"

例如:

    <table style="font-size: 20px;border-style: solid">
        <thead>
            <td>城市</td>
        </thead>
        <tbody th:each="city, stat : ${cities}">
            <tr>
                <td th:text="|${city},索引是:${stat.index},计数是:${stat.count},现在的对					    象:${stat.current}|"></td>
            </tr>
        </tbody>
    </table>

结果:

image-20210126152746066

该属性的作用域是该属性所在的标签内,出了这个标签就无法使用定义的变量。

注意:即使不定义状态变量名,Thymeleaf也会始终为每个th:each创建一个状态变量,默认状态变量名称就是自定义的元素变量名称加上Stat字符串。

条件判断

条件判断语句有三种:th:ifth:unlessth:switch

th:if

当表达式结果为真时显示内容,否则不显示。

${param != null}时:

真假判断依据是:

  • 当表达式值不为空null时:
    • 如果表达式值为Boolean类型,且值为true,则为真,否则为假
    • 如果表达式值是数字类型,且值为非0,则为真,否则为假
    • 如果表达式值是字符类型,且值为非0,则为真,否则为假
    • 如果表达式值是字符串类型,且值为非falseoffno,为真,否则为假
    • 如果表达式值不是布尔、数字、字符或字符串则为真
  • 当表达式值为空null时,评估结果为假

th:unless

它与th:if正好相反,当表达式的判断结果为false时显示内容,否则不显示。

th:switch

多路选择语句,与th:case来使用:

<div th:switch="${user.role}">
    <p th:case="admin">管理员</p>
    <p th:case="user">普通用户</p>
</div>

定义局部变量

使用th:with属性,可以定义局部变量,格式为:th:with="变量名=变量值"

定义多个局部变量时使用,分隔开。

内联表达式

内联表达式允许直接在HTML文本中使用标准表达式,而不需要使用th:*标签属性。

[[...]]

[[]]相当于th:text。不会对HTML标签转义。

[()]

相当于th:utext,会对HTML标签自动转义。

例子:

    @RequestMapping("/thymeleaf")
    public String getIndex(Model model) {
        model.addAttribute("data", "<h1>Hello World!</h1>");
        return "index";
    }

html文件:

    <span>[[${data}]]</span>
    <span>[(${data})]</span>
image-20210126200029833

th:inline

使用[[]][()]可以直接在HTML中使用 标准表达式,如果要使用更多功能。可以使用th:inline属性。它的取值有:

  • none:禁止内联表达式,可以原样输出[[]]和[()]字符串
  • text:文本内联,可以使用th:each等语法
  • css:样式内联,如<style th:inline="css">
  • javascript:脚本内联,如<style th:inline="javascript">

注释

有两种注释,一种是标准注释,注释的代码块会在文件源代码中显示出来。

一种是解析器级注释,注释的代码块会在引擎解析的时候去掉。

标准注释

语法:<!--内容--->

解析器级注释

语法:<!--/*内容*/-->

posted @ 2021-02-23 11:51  ZhaoQuaner  阅读(1659)  评论(0)    收藏  举报