> 文章列表 > Thymeleaf

Thymeleaf

Thymeleaf

1.引入Thymeleaf依赖

在pom.xml文件中添加Thymeleaf的场景启动器spring-boot-starter-thymeleaf。

<!--Thymeleaf模板引擎依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency>

2.创建模板文件

在resources/templates目录下创建模板文件thymeleaf.html。

标签中导入Thymeleaf的名称空间,为了Thymeleaf的语法提示和标签的使用。

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

 最终模板文件代码如下:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Thymeleaf demo</title>
</head>
<body>
<p>description字段值为:</p>
<p th:text="${description}">这里显示的是description字段内容</p>
</body>
</html>

3.编辑Controller代码

在controller包下新建ThymeleafController.java文件,将模板文件所需的description字段赋值并转发至模板文件。

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;import javax.servlet.http.HttpServletRequest;@Controller
public class ThymeleafController {@GetMapping("/thymeleaf")public String hello(HttpServletRequest request,@RequestParam(value = "description",required = false,defaultValue = "springboot-thymeleaf")String description){request.setAttribute("description",description);return "thymeleaf";}
}

效果图如下

可以看到html中的标签呗替换为“springboot-thymeleaf”而不是以下默认内容 

4.Thymeleaf模板引擎使用注意事项 

1.模板引擎的后缀名称注意事项

虽然Thymeleaf模板引擎文件的后缀名称是.html,但是这种文件严格来说并不属于静态资源文件,而是模板文件,存放的目录也是在模板目录中,与前文中演示的HTML静态页面有一些区别。第7章用到的test.html页面是放在static目录中的,部署后可以直接访问其路径。但是模板引擎文件一般不允许直接访问,而是要经过Controller控制器的处理,将动态数据返回到模板文件中进行读取并渲染的。比如本章演示的几个请求,都在控制器中实现了对应的方法并最终返回一个Thymeleaf视图对象在浏览器中呈现。

2.必须引入名称空间

名称空间引入方法如下所示:

 虽然不引入以上名称空间,静态资源访问和模板动态访问也不会报错,但是建议在开发过程中最好引入该名称空间。因为在引入之后会有Thymeleaf代码的语法提示,能够提升开发效率,也能减少人为造成的低级错误。有些开发人员可能会忽略这个事情。

3.禁用模板缓存

Thymeleaf的默认缓存设置是通过配置文件的spring.thymeleaf.cache配置属性决定的。该属性默认为true,因此Thymeleaf默认是使用模板缓存的。该设置有助于改善应用程序的性能,因此模板只需编译一次即可。除非重启应用程序,否则在开发过程中不能实时看到页面变更的效果,因此建议将该属性设置为false,在配置文件application.properties中修改代码如下所示:

#设置thymeleaf模板引擎的缓存,设置为false,默认为true
spring.thymeleaf.cache=false

4.Thymeleaf属性值

修改属性值实践

html页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Thymeleaf setting-value-to-specific-attributes</title>
</head>
<body th:background="${th_background}" background="#D0D0D0">
<!--text标签-->
<h1 th:text="${title}">html标签演示</h1>
<div><h5>id、name、value标签:</h5><!--id、name、value标签--><input id="input1" name="input1" value="1" th:id="${th_id}" th:name="${th_name}" th:value="${th_value}"/>
</div>
<br>
<div class="div1" th:class="${th_calss}"><h5>class、href</h5><a th:href="${th_href}" href="##/">链接地址</a>
</div>
</body>
</html>

后端请求转发代码

@GetMapping("/attributes")public String attributes(ModelMap map){//更改html内容map.put("title","Thymeleaf标签演示");//更改id、name、valuemap.put("th_id","thymeleaf-input");map.put("th_name","thymeleaf-input");map.put("th_value","13");//更改class、hrefmap.put("th_class","thymeleaf-class");map.put("th_href","http://13blog.site");return "attributes";}

5.Thymeleaf语法

5.1表达式语法

①变量表达式:${...}
②选择变量表达式:*{...}
③信息表达式:#{...}
④链接URL表达式:@{...}
⑤分段表达式:~{...}

5.2字面量

①字符串:'one text'、'Another one!' ......
②数字:0, 34、3.0、12.3 ......
③布尔值:true、false
④Null值:null
⑤字面量标记:one、sometext、main ......

5.3文本运算

①字符串拼接:+
②字面量置换: |The name is ${name}|

5.4算术运算

①二元运算符:+、-、*、/、%
②负号(一元运算符):(unary operator): -

5.5布尔运算

①二元运算符:and、or
②布尔非(一元运算符):!、not

5.6比较运算

①比较:>、<、>=、<= (gt、lt、ge、le)
②相等运算符:==、!= (eq、ne)
比较运算符也可以使用转义字符,比如大于号,可以使用Thymeleaf语法gt,也可以使用转义字符“&gt;”。

5.7条件运算符

①If-then: (if) ? (then)
②If-then-else: (if) ? (then) : (else)
③Default: (value) ?: (defaultvalue)

5.8特殊语法

无操作:_

5.9Thymeleaf简单语法实践

html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Thymeleaf simple syntax</title>
</head>
<body>
<h1>Thymeleaf简单语法</h1>
<div><h5>基本类型操作(字符串)</h5><p>一个简单的字符串:<span th:text="'thymeleaf'">default text</span>.</p><p>字符串的连接:<span th:text="'thymeleaf text concat,'+${thymeleafText}">default text</span>.</p><p>字符串的连接:<span th:text="|thymeleaf text concat,${thymeleafText}|">default text</span>.</p>
</div>
<div><h5>基本类型操作(数字):</h5><p>一个简单的神奇的数字:<span>1000</span>.</p><p>算术运算:2021 + 1 =<span th:text="${number1}+1">0</span>.</p><p>算术运算:14 - 1 =<span th:text="14-1">0</span>.</p><p>算术运算:1011 * 2 =<span th:text="1011*${number2}">0</span>.</p><p>算术运算:39 / 3 =<span th:text="39/3">0</span>.</p>
</div>
<div><h5>基本类型操作(布尔值):</h5><p>一个简单的数字比较:2022>2021=<span th:text="2022&gt;2021"> </span>.</p><p>字符串比较: thymeleafText == 'spring-boot',结果为<span th:text="${thymeleafText} == 'spring-boot'">0</span>.</p><p>数字比较:13 == 39/3 结果为:<span th:text="13 == 39/3">0</span>.</p>
</div>
</body>
</html>

java

@GetMapping("/simple")public String simple(ModelMap map){map.put("thymeleafText","spring-boot");map.put("number1",2021);map.put("number2",2);return "simple";}

5.10Thymeleaf表达式

(1)变量表达式(写法:${...})

常见的有:取值赋值,逻辑判断,循环语句。

也可以使用内置的基本对象 :

①ctx:上下文对象
②vars:上下文变量
③locale:上下文语言环境
④request:在Web环境下的HttpServletRequest对象
⑤response:在Web环境下的HttpServletResponse对象
⑥session:在Web环境下的HttpSession对象
⑦servletContext:在Web环境下的ServletContext对象

 还提供了一系列Utility工具对象(内置于Context中),可以通过#直接访问,工具对象如下所示。
①dates:java.util.Date的功能方法类
②calendars:类似#dates,面向java.util.Calendar
③numbers:格式化数字的工具方法类
④strings:字符串对象的工具方法类,contains、startWiths、prepending/appending等
⑤bools:求布尔值的工具方法
⑥arrays:数组的工具方法
⑦lists:java.util.List的工具方法
⑧sets:java.util.Set的工具方法
⑨maps:java.util.Map的工具方法

(2)选择(星号)表达式

选择表达式与变量表达式类似,不过它会用一个预先选择的对象代替上下文变量容器来执行。语法为*{goodsName}。被指定的对象由th:object标签属性在外层进行定义。前文读取goodsDetail对象的goodsName字段可以替换为:

 

 

(3)URL表达式

th:href对应的是html中的href标签,它将计算并替换href标签中的URL地址,th:href可以直接设置为静态地址,也可以使用表达式语法对读取的变量值动态拼接为URL地址。
比如一个详情页的URL地址:

 当使用URL表达式时,可以写成这样:

 也可以根据id值进行替换,写法为:

 或者也可以写成这样:

 以上三种表达式生成的URL结果都是相同的。开发人员可以自己使用字符串拼接的方法组装URL(第二种写法),也可以使用URL表达式提供的语法进行URL组装(第三种写法)。如果有多个参数可以自行拼装字符串,或者使用逗号进行分隔,写法如下:

 最终生成的URL为“http://localhost:8080/goods/1?title=iPhone13&tag=手机”。另外,URL中以"/" 开头的路径(比如/goods/1),默认生成的URL会加上该项目的当前地址形成完整的URL。

(4)Thymeleaf复杂语法实践

html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title th:text="${tiitle}">语法测试</title>
</head>
<body><h3>#strings工具类测试</h3>
<div th:if="${not #strings.isEmpty(testString)}"><p>testString初始值: <span th:text="${testString}"></span></p><p>toUpperCase : <span th:text="${#strings.toUpperCase(testString)}"></span></p><p>toLowerCase : <span th:text="${#strings.toLowerCase(testString)}"></span></p><p>equalsIgnoreCase: <span th:text="${#strings.equalsIgnoreCase(testString,'13')}"></span></p><p>indexOf : <span th:text="${#strings.indexOf(testString,'r')}"></span></p><p>substring : <span th:text="${#strings.substring(testString,1,4)}"></span></p><p>startsWith : <span th:text="${#strings.startsWith(testString,'Spring')}"></span></p><p>contains : <span th:text="${#strings.contains(testString,'Boot')}"></span></p>
</div><h3>#bools工具类测试</h3>
<!--如果bool的值为false的话,该div将不会显示-->
<div th:if="${#bools.isTrue(bool)}"><p th:text="${bool}"></p>
</div><h3>#arrays 工具类测试</h3>
<div th:if="${not #arrays.isEmpty(testArray)}"><p>length : <span th:text="${#arrays.length(testArray)}"></span></p><p>contains : <span th:text="${#arrays.contains(testArray,5)}"></span></p><p>containsALL :<span th:text="${#arrays.containsAll(testArray,testArray)}"></span></p><p>循环读取 :<span th:each="i:${testArray}" th:text="${i+' '}"></span></p>
</div><h3>#lists 工具类测试</h3>
<div th:unless="${#lists.isEmpty(testList)}"><p>size : <span th:text="${#lists.size(testList)}"></span></p><p>contains : <span th:text="${#lists.contains(testList,0)}"></span></p><p>sort : <span th:text="${#lists.sort(testList)}"></span></p><p>循环读取 : <span th:each="i:${testList}" th:text="${i+' '}"></span></p>
</div><h3>#maps 工具类测试</h3>
<div th:if="${not #maps.isEmpty(testMap)}"><p>size : <span th:text="${#maps.size(testMap)}"></span></p><p>containsKey : <span th:text="${#maps.containsKey(testMap,'platform')}"></span></p><p>containsValue : <span th:text="${#maps.containsValue(testMap,'13')}"></span></p><p>读取map中键为title的值 : <span th:if="${#maps.containsKey(testMap,'title')}" th:text="${testMap.get('title')}"></span></p>
</div><h3>#dates 工具类测试</h3>
<div><p>year : <span th:text="${#dates.year(testDate)}"></span></p><p>month : <span th:text="${#dates.month(testDate)}"></span></p><p>day : <span th:text="${#dates.day(testDate)}"></span></p><p>hour : <span th:text="${#dates.hour(testDate)}"></span></p><p>minute : <span th:text="${#dates.minute(testDate)}"></span></p><p>second : <span th:text="${#dates.second(testDate)}"></span></p><p>格式化 :<span th:text="${#dates.format(testDate)}"></span></p><p>yyyy-MM-dd HH:mm:ss 格式化 : <span th:text="${#dates.format(testDate,'yyyy-MM-dd HH:mm:ss')}"></span></p>
</div>
</body>
</html>

java

@GetMapping("/complex")public String complex(ModelMap map){map.put("title","Thymeleaf语法测试");map.put("testString","Spring Boot 商城");map.put("bool",true);map.put("testArray",new Integer[]{2021,2022,2023,2024});map.put("testList", Arrays.asList("Spring","Spring Boot","Thymeleaf","MyBatis","Java"));HashMap<Object, Object> testMap = new HashMap<>();testMap.put("platform","book");testMap.put("title","Spring Boot 商城项目实战");testMap.put("author","十三");map.put("testMap",testMap);map.put("testDate",new Date());return "complex";}