thymeleaf基本语法
Spring Boot整合Thymeleaf 模版
SpringBoot项目默认不是JSP,那如何来实现我们的动态页面呢?SpringBoot推荐模板引擎Thymeleaf。其实JSP也属于一种模板引擎,比较常用的还有freemaker。模板引擎非常多,道理都一样
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
spirngboot默认配置了Thymeleaf
也可以自己写
spring:
thymeleaf:
prefix: classpath:/templates/
suffix: .html
mode: HTML
encoding: UTF-8
如果希望客户端可以直接访问 HTML 资源,将这些资源放置在 static 路径下即可,否则必须通过 Handler 的后台映射才可以访问静态资源。
注意使用时一定别忘了导入命名空间
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body>
</html>
创建模板文件
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" >
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p th:text="${msg}"></p>
<!-- 方式1 -->
<p th:text="'提示:'+${msg}"></p>
<!-- 方式2 -->
<p> 提示:[[${person.name}]] </p>
</body>
</html>
-
<html xmlns:th="http://www.thymeleaf.org">
是引入thymeleaf的命名空间,必须。 -
可以在原来的任何属性前面加上前缀
th:*
来表示thymeleaf的定义。data-th-*
效果一样。 -
在标签内拼接字符串比较麻烦,可以在里面通过[[]]来显示跟拼接
定义页面
在classpath:templates
路径下创建html文件作为显示页面,一定要放在此路径,并且一定要是html格式,比如hello.html
简单表达式
Thymeleaf 提供了非常丰富的标准表达式语法,总共有 8 大类:
-
简单表达式
-
字面值
-
文本操作
-
算术运算
-
布尔运算
-
比较和相等
-
条件运算
-
无操作符
语法 | 名称 | 描述 | 作用 |
---|---|---|---|
${…} | Variable Expressions | 变量表达式 | 取出上下文变量的值 |
*{…} | Selection Variable Expressions | 选择变量表达式 | 取出选择的对象的属性值 |
#{…} | Message Expressions | 消息表达式 | 使文字消息国际化,I18N |
@{…} | Link URL Expressions | 链接表达式 | 用于表示各种超链接地址 |
~{…} | Fragment Expressions | 片段表达式 | 引用一段公共的代码片段 |
Thymeleaf 常用语法
定义局部变量
使用th:with
属性可以定义局部变量
<span th:with="myName='dyk'">
<p th:text="${myName}" ></p>
</span>
同时定义多个局部变量时,用英文,
号分隔开
<p th:with="name=${user.name},age={user.age}">
......
</p>
注释
标准注释
- 标准注释会在文件源代码中显示出来。
<!-- --->
析器级注释
-
注释的代码块会在引擎解析的时候抹去。
<!--/* ... */-->
取值
和原来jsp的el表达式类似
package com.blb.springbootmybatis.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class ThymeleafController {
@GetMapping("/test1")
public ModelAndView test(){
ModelAndView modelAndView=new ModelAndView();
modelAndView.addObject("name","dyk");
modelAndView.setViewName("test");
return modelAndView;
}
}
<!--th:text就是将div中的内容设置为它指定的值,和Vue有点像
一样-->
<div th:text="${name}"></div>
拼接
<div th:text="'我的名字是'+${name}+'年龄是'+18"></div>
单引号加+号拼接
或者直接双引号里面使用| 拼接的内容 |
<div th:text="|我叫${name}|"></div>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div th:text="${name}"></div>
<div th:text="'我的名字是'+${name}+'年龄是'+18"></div>
<div th:text="|我叫${name}|"></div>
</body>
</html>
*{…}
变量表达式${}
是面向整个上下文的,而选择变量表达式*{}
的上下文是父标签(th:object
)所选择的对象。
// Person bean
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Person {
private String name ;
private String sex ;
private Integer age ;
}
// controller
@RequestMapping("/hello")
public String welcome(Model model){
Person person = new Person("dyk","男",18);
model.addAttribute("person",person);
return "hello" ;
}
<span th:object="${person}">
<p th:text="*{name}"></p>
<p th:text="*{sex}"></p>
<p th:text="*{age}"></p>
</span>
<!-- 跟下面效果等效 -->
<span >
<p th:text="${person.name}"></p>
<p th:text="${person.sex}"></p>
<p th:text="${person.age}"></p>
</span>
内联表达式
内联表达式允许我们直接在 HTML 文本中使用标准表达式,而不需要使用th:*
标签属性
[[ ]]
[[]]
相当于th:text
,对含有 HTML 标签的内容自动进行字符转义
<p>[[${msg}]]</p>
[( )]
[()]
相当于th:utext
,对含有 HTML 标签的内容不进行字符转义
<p>[(${msg})]</p>
th:inline
我们已经了解到,使用[[]]
和[()]
语法可以直接在 HTML 文本中使用标准表达式,如果想要使用更多高级的功能,需要使用th:inline
属性来激活,它的取值如下
值 | 描述 |
---|---|
none | 禁止内联表达式,可以原样输出 [[]] 和 [()] 字符串 |
text | 文本内联,可以使用 th:each 等高级语法 |
css | 样式内联,如<style th:inline="css"> |
javascript | 脚本内联,如:<style th:inline="javascript"> |
-
none
<!-- [[ ]]不会被解析,原字符串输出 --> <p th:inline="none">[[asdfsafd]]</p>
-
text
<p th:inline="text">[[${msg}]]</p>
-
css
<style th:inline="css"> body { background-color:[[${bgColor}]]; } </style>
字面值
所谓字面值,首先它不是一个变量,它是一个具体的确切的值,通常这些值是比较简单的,例如:18
、'welcome'
等,它们没有名称,以至于我们只能用值来称呼它们,因此我们称其为字面值
文字字面值
- 文字字面值是用单引号引起来的任何字符内容,如果字符内容里面含有单引号,则需要进行转义
<p th:text="'Welcome to bailiban...'"></p>
数字字面值
<!-- 2019 -->
<p th:text="2019"></p>
<!-- 2020 -->
<p th:text="2019 + 1"></p>
布尔字面值
<!-- false -->
<p th:text="true"></p>
<!-- false -->
<p th:text="1 > 2"></p>
<!-- 否 -->
<p th:text="1 > 2 ? '是' : '否'"></p>
空字面值
<!-- false -->
<p th:text="${user == null}"></p>
字符串连接
不管是字面值还是表达式的结果,我们都可以使用+
符号将它们连接起来:
<p th:text="'Welcome to ' + ${msg} + '!'"></p>
字面值替换
符号||
可以用来将字面值和表达式包裹起来,这样就能方便的替换变量的值,而不需要使用+
连接符:
<p th:text="|Welcome to ${msg} !|"></p>
算术运算
支持+
(加)、-
(减)、*
(乘)、/
(除)、%
(模)运算。
<!-- 6 -->
<p th:text="4 + 2"></p>
<!-- 2 -->
<p th:text="4 - 2"></p>
<!-- 8 -->
<p th:text="4 * 2"></p>
<!-- 2 -->
<p th:text="4 / 2"></p>
<!-- 0 -->
<p th:text="4 % 2"></p>
<!-- 2 -->
<p th:text="${page + 1}"></p>
<!-- 2 -->
<p th:text="${page} + 1"></p>
布尔运算
支持and
(且)、or
(或)、!
(非)、not
(非)运算
<!--true-->
<p th:text="${true and true}"></p>
<!--true-->
<p th:text="${true or false}"></p>
<!--false-->
<p th:text="${!true}"></p>
<!--true-->
<p th:text="${not false}"></p>
比较运算
支持<
(lt
)、>
(gt
)、<=
(le
)、>=
(ge
)、==
(eq
)、!=
(ne
)
<p th:text="${person.age < 60}"></p>
<p th:text="${person.age <= 60}"></p>
<p th:text="${person.age > 18}"></p>
<p th:text="${person.age >= 18}"></p>
<p th:text="${person.age == 18}"></p>
<p th:text="${person.age != 18}"></p>
- gt great than 大于
- ge great equal 大于等于
- eq equal 等于
- lt less than 小于
- le less equal 小于等于
- ne not equal 不等于
三元运算
(if) ? (then) : (else)
<input th:value="${name == 'dyk'? '是':'不是'}"/>
<div th:text="${age >= 20? '青年':'少年'}"></div>
<div th:text="${age ge 20? '青年':'少年'}"></div>
<p >[[${person.age >= 18?'成年':'未成年'}]]</p>
二元运算符
(value) ?: (defaultValue)
其中,value
非空(null)即真,条件为真时输出value
,否则输出defaultValue
。
<p th:text="${person.name}?:'用户名不能为空'"></p>
也可以使用无操作符达到相同效果。_
表示显示标签体内的内容。
<p th:text="${person.name}?:_">用户名不能为空</p>
使用文本
th:text
在标签体中展示表达式评估结果的文本内容
<p th:text="${message}">Welcome to bailiban!</p>
当它作为静态文件直接运行时,浏览器会自动忽略它不能识别的th:text
属性,而显示标签体的文本内容Welcome to bailiban!
当它作为模板文件运行在服务器端时,th:text
属性的具体值将会替换标签体的文本内容
th:utext
utext
跟text
的区别是utext会解析html标签,而text
不会。
假设model.addAttribute("msg","<b>welcome to bailiban ...</b> ");
<!--<b>welcome to bailiban ...</b> -->
<p th:text="${msg}"></p>
<!-- 显示welcome to bailiban ...,字体变粗,解析b标签的结果-->
<p th:utext="${msg}"></p>
设置属性
在 Thymeleaf 模板文件中,你可以使用th:*
(或者使用th:attr
属性)来设置任意的 HTML5 标签属性的值。不仅如此,你还可以th:*-*
来同时为多个不同的标签属性设置相同的一个值,甚至你可以使用th:attrappend
和th:attrprepend
来追加新的值到现有的标签属性值中
th:attr
这种方式是不被推荐的,了解一下就行。下面是用th:attr="href=..."
来设置标签href
属性的值
<a th:attr="href=@{https://www.google.com}">谷歌一下你就知道</a>
th:*
th:attr
不够简洁,我们推荐下面的方式
<a th:href="@{https://www.google.com}">谷歌一下你就知道</a>
其中的*
可以是HTML5中的任意属性
th:*-*
如果想要同时为标签的多个不同属性设置相同的一个值,可以使用th:*-*
的语法
<img src="logo.png" th:alt-title="LOGO图片">
它相当于:
<img src="logo.png" th:alt="LOGO图片" th:title="LOGO图片">
th:attrappend & th:attrprepend
<!-- <button class="btn disable ">购买</button> -->
<button class="btn" th:attrappend="class=' disable '">购买</button>
<!-- <button class=" disable btn">购买</button> -->
<button class="btn" th:attrprepend="class=' disable '">购买</button>
布尔属性
在 HTML 中有些属性是布尔属性,布尔属性是指没有值的属性,如readonly
、checked
、selected
等。它们若存在那就意味着值为 true。 Thymeleaf 也允许我们通过th:*
(这里的*
表示任意的布尔属性) 来选择是否使用这些布尔属性
<input type="checkbox" th:checked="${remember}" /> 记住我
当${remember}
为null就不会默认选中,不为null则会默认勾选上
条件判断
th:if
th:if 表示条件成立时显示内容
当表达式的评估结果为真时则显示内容,否则不显示
<div th:if="${name=='dyk'}" th:text="${name}"></div>
<div th:if="${name=='dyk'}" >[[${name}]]</div>
取值也可以不写在标签里面,通过两个中括号
th:unless
th:unless 表示条件不成立时显示内容
th:unless
与th:if
判断恰好相反,当表达式的评估结果为假时则显示内容,否则不显示
<div th:unless="${name=='cb'}" th:text="${name}"></div>
<div th:unless="${name=='cb'}">[[${name}]]</div>
由于我存的name值是dyk不等于cb所以会取出来
th:swith
多路选择语句,它需要搭配th:case
来使用:
switch
@GetMapping("/switch")
public String switchTest(Model model){
model.addAttribute("gender","女");
return "test";
}
<div th:switch="${gender}">
<p th:case="女">女</p>
<p th:case="男">男</p>
<p th:case="*">未知</p>
</div>
<div th:switch="${person.sex}">
<p th:case="男">man</p>
<p th:case="女">girl</p>
</div>
循环遍历
遍历(迭代)的语法th:each="自定义的元素变量名称 : ${集合变量名称}"
<table border="1px solid #000">
<tr>
<th>id</th>
<th>username</th>
<th>password</th>
<th>hobby</th>
<th>email</th>
<th>操作</th>
</tr>
<tr th:each="user:${users}">
<td th:text="${user.id}"></td>
<td th:text="${user.username}"></td>
<td th:text="${user.password}"></td>
<td th:text="${user.hobby}"></td>
<td th:text="${user.email}"></td>
</tr>
</th>
</table>
- 属性
th:each
提供了一个用于跟踪迭代的状态变量,stat 状态变量的使用语法:th:each="自定义的元素变量名称, 自定义的状态变量名称 : ${集合变量名称}"
。 它包含以下几个属性 :
属性 | 类型 | 描述 |
---|---|---|
index | int | 当前迭代的索引,从 0 开始 |
count | int | 当前迭代的计数,从 1 开始 |
size | int | 集合中元素的总个数 |
current | int | 当前的元素对象 |
even | boolean | 当前迭代的计数是否是偶数 |
odd | boolean | 当前迭代的计数是否是奇数 |
first | boolean | 当前元素是否是集合的第一个元素 |
last | boolean | 当前元素是否是集合的最后一个元素 |
各行变色表格
<table border="1px solid #000">
<tr>
<th>id</th>
<th>username</th>
<th>password</th>
<th>hobby</th>
<th>email</th>
<th>操作</th>
</tr>
<tr th:each="user,stat:${users}" th:style="'background-color:'+@{${stat.odd}?'#F2F2F2'}">
<td th:text="${user.id}"></td>
<td th:text="${user.username}"></td>
<td th:text="${user.password}"></td>
<td th:text="${user.hobby}"></td>
<td th:text="${user.email}"></td>
<td>
<a href="/toAddPage">添加</a>
<a href="/delete/${user.id}">删除</a>
<a href="/toUpdatePage/${user.id}">修改</a>
</td>
</tr>
</th>
</table>
URL @{…} 链表表达式
Thymeleaf 对于 URL 的处理是通过 @{...}
进行处理,结合 th:href 、th:src
绝对地址
<a th:href="@{http://www.baidu.com}" th:text="baidu"></a>
相对地址
<!-- 不带参数 -->
<a th:href="@{hello2}" th:text="hello2"></a> <br/>
<!-- 带参数 -->
<a th:href="@{hello2(name=${person.name},password='123')}" th:text="hello2"></a> <br/>
- 页面跳转必须通过后台controller
- 参数都放在
()
括号内,参数之间用,
号隔开 - 参数值变量通过
${}
引用
<a th:href="@{http://www.baidu.com}">跳转</a>
<a th:href="@{http://localhost:9090/index/url/{na}(na=${name})}">跳转2</a>
<img th:src="${src}">
<div th:style="'background:url('+ @{${src}} +');'">
<br/>
<br/>
<br/>
</div>
复用代码片段~{…}
~{…}片段表达式主要用来引用一段可重复使用的代码片段
- base/common.html
<div th:fragment="foot-copy" >
Copyright © 2012-2019 管理系统 - Version V1.1
</div>
- hello.html
<div th:insert="~{base/common::foot-copy}"></div>
-
base/common
是文件路径,foot-copy
是定义的th:fragment
值,用::
分割。
-
~{}
可以省略。
除了使用th:fragment
还可以通过选择器来引用。 -
base/common.html
<div class="foot-copy" >
Copyright © 2012-2019 管理系统 - Version V1.1
</div>
- hello.html
<div th:insert="~{base/common::.foot-copy}"></div>
.foot-copy
是CSS选择器去匹配。
我们定义代码片段时还可以声明一组参数:
- base/common.html
<div th:fragment="menu(menuName1, menuName2)">
<p th:text="${menuName1}"></p>
<p th:text="${menuName2}"></p>
</div>
- hello.html
<div th:insert="~{base/common::menu('用户中心', '我的订单')}"></div>
th:insert
跟th:replace
的区别?
他们都是用来使用代码片段, th:insert 如同插入的字面意思,将指定的代码片段插入主标签内 。 th:replace 如同替换的字面意思,将主标签替换为指定的代码片段。
基本对象
对象 | 描述 |
---|---|
#ctx | 上下文对象 |
#vars | 同 #ctx,表示上下文变量 |
#locale | 上下文本地化(特定的地理区域)变量,可参考 java.util.Locale |
#request | HttpServletRequest 对象,可参考 javax.servlet.http.HttpServletRequest |
#response | HttpServletResponse 对象,可参考 javax.servlet.http.HttpServletResponse |
#session | HttpSession 对象,可参考 javax.servlet.http.HttpSession |
#servletContext | ServletContext 对象,可参考 javax.servlet.ServletContext |
#request
<!-- HTTP/1.1 -->
<p th:text="${#request.protocol}"></p>
<!-- http -->
<p th:text="${#request.scheme}"></p>
<!-- localhost -->
<p th:text="${#request.serverName}"></p>
<!-- 8080 -->
<p th:text="${#request.serverPort}"></p>
<!-- GET -->
<p th:text="${#request.method}"></p>
<!-- /hello -->
<p th:text="${#request.requestURI}"></p>
<!-- http://localhost:8080/hello -->
<p th:text="${#request.requestURL}"></p>
<!-- /hello -->
<p th:text="${#request.servletPath}"></p>
<!-- zhangsan -->
<p th:text="${#request.getAttribute('student').name}"></p>
<!-- name=zhang -->
<p th:text="${#request.queryString}"></p>
#response
<!-- 200 -->
<p th:text="${#response.status}"></p>
<!-- 8192 -->
<p th:text="${#response.bufferSize}"></p>
<!-- UTF-8 -->
<p th:text="${#response.characterEncoding}"></p>
<!-- text/html;charset=UTF-8 -->
<p th:text="${#response.contentType}"></p>
#session
<!-- 需要在后台开启会话,存入person数据 -->
<!-- BFE8F9E54C863E128B107532A902E921 -->
<p th:text="${#session.id}"></p>
<!-- 1499786693244 -->
<p th:text="${#session.lastAccessedTime}"></p>
<!-- seven -->
<p th:text="${#session.getAttribute('person').name}"></p>
@GetMapping("/object")
public String object(HttpServletRequest request){
request.setAttribute("request","request对象");
request.getSession().setAttribute("session","session对象");
return "test";
}
<p th:text="${#request.getAttribute('request')}"></p>
<p th:text="${#session.getAttribute('session')}"></p>
<p th:text="${#locale.country}"></p>
内嵌对象
可以直接通过 # 访问。
对象 | 作用 |
---|---|
dates | java.util.Date 的功能方法 |
calendars | java.util.Calendar 的功能方法 |
numbers | 格式化数字 |
strings | java.lang.String 的功能方法 |
objects | Object 的功能方法 |
bools | 对布尔求值的方法 |
arrays | 操作数组的功能方法 |
lists | 操作集合的功能方法 |
sets | 操作集合的功能方法 |
maps | 操作集合的功能方法 |
@GetMapping("/util")
public String util(Model model){
model.addAttribute("name","zhangsan");
model.addAttribute("users",new ArrayList<>());
model.addAttribute("count",22);
model.addAttribute("date",new Date());
return "test";
}
<!-- 格式化时间 -->
<p th:text="${#dates.format(date,'yyyy-MM-dd HH:mm:sss')}"></p>
<!-- 创建当前时间,精确到天 -->
<p th:text="${#dates.createToday()}"></p>
<!-- 创建当前时间,精确到秒 -->
<p th:text="${#dates.createNow()}"></p>
<!-- 判断是否为空 -->
<p th:text="${#strings.isEmpty(name)}"></p>
<!-- 判断List是否为空 -->
<p th:text="${#lists.isEmpty(users)}"></p>
<!-- 输出字符串长度 -->
<p th:text="${#strings.length(name)}"></p>
<!-- 拼接字符串 -->
<p th:text="${#strings.concat(name,name,name)}"></p>
<!-- 创建自定义字符串 -->
<p th:text="${#strings.randomAlphanumeric(count)}"></p>