基于Springboot 的Thymeleaf模板引擎
第一章:Thymeleaf 模板引擎的简介
Thymeleaf是面向Web和独立环境的服务器Java模板引擎,能够处理HTML、XML、JavaScript、CSS甚至纯文本数据。
Thymeleaf的主要目标在于提供一种可被浏览器正确显示的、格式良好的模板创建方式,因此也可以用作静态建模。
Thymeleaf的可扩展性也非常棒。你可以使用它定义自己的模板属性集合,这样就可以计算自定义表达式并使用自定义逻辑。这意味着Thymeleaf还可以作为模板引擎框架。
1.1、Thymeleaf可以处理什么模板
Thymeleaf允许我们处理六种模板:
- HTML
该HTML模板模式将允许任何类型的HTML的输入,包括HTML5,HTML4和XHTML。 - XML
该XML模板模式将允许XML输入。在这种情况下,代码应该是格式良好的 - 没有未封闭的标签,没有未加引号的属性等等,如果发现格式错误,解析器将会抛出异常。 - TEXT
该TEXT模板模式将允许非标记性质的模板使用特殊的语法。这种模板的例子可能是文本电子邮件或模板文档。
- JAVASCRIPT
该JAVASCRIPT模板模式将允许在Thymeleaf应用程序的JavaScript文件的处理。
- CSS
该CSS模板模式将允许参与Thymeleaf应用CSS文件的处理。
- RAW
该RAW模板模式将根本不处理模板。
1.3、标准的Thymeleaf模板
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Good Thymes Virtual Grocery</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" media="all"
href="../../css/gtvg.css" th:href="@{/css/gtvg.css}" />
</head>
<body>
<p th:text="#{home.welcome}">Welcome to our grocery store!</p>
</body>
</html>
第二章:搭建基于SpringBoot的Thymeleaf环境
工程环境图
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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sudojava.springboot_thymeleaf</groupId>
<artifactId>springboot_thymeleaf</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springboot_thymeleaf</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</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-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
配置application.properties文件
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=UTF-8
#配置Hibernate的基本属性
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
第三章:标准表达式语法
Thymeleaf Standard Expression是Thymeleaf中语法中最重要的部分之一,以下是标准表达式功能的总结:
注意:Thymeleaf模板语法,都是以th属性开头:<span th:text=".....">
1、简单表达式:
- 变量表达式:${...}
- 选择变量表达式:*{...}
- 消息表达式:#{...}
- 链接URL表达式:@{...}
- 片段表达式:~{...}
2、字面
- 文本字面:'one text','Another one!',...
- 号码文字:12,34,6,7,8,.....
- 布尔文字:true、false
- 空文字:null
- 文字标记:one、sometext、main, …...
3、文字操作
- 字符串连接: +
- 文字替换: |The name is ${name}|
4、算术运算:
- 二元运算符:+, - , * , / , %
- 减号(一元运算符)
5、布尔运算符:
- 二元运算符:and,or
- 布尔否定:!,not
6、逻辑运算符
- 比较运算符:> , < , >= ,<= (gt,lt,ge,le)
- 布尔运算符:==,!=(eq,ne)
7、IF ELSE判断:
- IF-THEN: (if) ? (then)
- IF-THEN-ELSE: (if) ? (then) : (else)
3.1.1、变量表达式
${…} 表达式实际上是包含了上下文中的变量映射执行的OGNL(对象图导航语言)表达式。
测试案例:
HTML页面代码
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title></title>
<meta charset="utf-8"/>
<link th:href="@{css/bootstrap.min.css}" rel="stylesheet"/>
</head>
<body>
<p>Today is: <span th:text="${day}"></span>.</p>
<p>FirstName is <span th:text="${user.firstName}"></span> </p>
<p>lastName is <span th:text="${user.lastName}"></span> </p>
</body>
</html>
Java代码
package com.sudojava.springboot_thymeleaf.controller;
import com.sudojava.springboot_thymeleaf.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.http.HttpServletRequest;
@Controller
public class IndexController {
@RequestMapping(value = "/",method = RequestMethod.GET)
public String index(Model model){
model.addAttribute("day","2007-12-12");
User user = new User();
user.setFirstName("zhang");
user.setLastName("san");
model.addAttribute("user",user);
return "/index";
}
}
3.1.2、选择表达式(星号语法)
可以简单理解为内层是对外层对象的引用。
HTML代码
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title></title>
<meta charset="utf-8"/>
<link th:href="@{css/bootstrap.min.css}" rel="stylesheet"/>
</head>
<body>
<div th:object="${user}">
<p>Name: <span th:text="*{firstName}">Sebastian</span>.</p>
<p>Surname: <span th:text="*{lastName}">Pepper</span>.</p>
</div>
</body>
</html>
以上代码等同于:
<div>
<p>Name: <span th:text="${user.firstName}">Sebastian</span>.</p>
<p>Surname: <span th:text="${user.lastName}">Pepper</span>.</p>
</div>
Java代码
package com.sudojava.springboot_thymeleaf.controller;
import com.sudojava.springboot_thymeleaf.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.http.HttpServletRequest;
@Controller
public class IndexController {
@RequestMapping(value = "/",method = RequestMethod.GET)
public String index(Model model){
model.addAttribute("day","2007-12-12");
User user = new User();
user.setFirstName("zhang");
user.setLastName("san");
model.addAttribute("user",user);
return "/index";
}
}
我们来看看Thymeleaf官网给提供的例子:
/*
* Access to properties using the point (.). Equivalent to calling property getters.
*/
${person.father.name}
/*
* Access to properties can also be made by using brackets ([]) and writing
* the name of the property as a variable or between single quotes.
*/
${person['father']['name']}
/*
* If the object is a map, both dot and bracket syntax will be equivalent to
* executing a call on its get(...) method.
*/
${countriesByCode.ES}
${personsByName['Stephen Zucchini'].age}
/*
* Indexed access to arrays or collections is also performed with brackets,
* writing the index without quotes.
*/
${personsArray[0].name}
/*
* Methods can be called, even with arguments.
*/
${person.createCompleteName()}
${person.createCompleteNameWithSeparator('-')}
3.1.3、表达式基本对象
在上下文变量上评估OGNL表达式时,一些对象可用于表达式以获得更高的灵活性。这些对象将被引用(按照OGNL标准),从#符号开始:
#ctx
:上下文对象。#vars:
上下文变量。#locale
:上下文语言环境。#request
:(只在Web上下文中)HttpServletRequest
对象。#response
:(只在Web上下文中)HttpServletResponse
对象。#session
:(只在Web上下文中)HttpSession
对象。#servletContext
:(只在Web上下文中)ServletContext
对象。
3.1.4、表达式工具对象
除了这些基本的对象之外,Thymeleaf还会为我们提供一套实用对象,帮助我们在表达式中执行常见任务。
#execInfo
:关于正在处理的模板的信息。#messages
:在变量表达式中获得外部化消息的方法,与使用#{...}语法获得的方式相同。#uris
:用于转义URL / URI部分的方法#conversions
:执行配置的转换服务的方法(如果有的话)。#dates
:java.util.Date
对象的方法:格式化,组件提取等#calendars
:类似于#dates
,但是对于java.util.Calendar
物体。#numbers
:格式化数字对象的方法。#strings
:String
对象的方法:contains,startsWith,prepending / appending等#objects
:一般对象的方法。#bools
:布尔评估的方法。#arrays
:数组的方法。#lists
:列表的方法。#sets
:套的方法。#maps
:地图的方法。#aggregates
:在数组或集合上创建聚合的方法。#ids
:处理可能重复的id属性的方法(例如,作为迭代的结果)。
3.1.5、URL链接地址
URL主要是实现了超链接点击的作用,包括地址栏传递参数等功能。
URL语法如下:
- 绝对网址:
http://www.thymeleaf.org
- 相对URL,可以是:
- 页面相对:
user/login.html
- 与上下文相关:(
/itemdetails?id=3
服务器中的上下文名称将自动添加) - 服务器相对:(
~/billing/processInvoice
允许在同一服务器中的另一个上下文(=应用程序)中调用URL。 - 与协议相关的网址:
//code.jquery.com/jquery-2.0.3.min.js
官网给我们的展示案例:
<!-- Will produce 'http://localhost:8080/gtvg/order/details?orderId=3' (plus rewriting) -->
<a href="details.html"
th:href="@{http://localhost:8080/gtvg/order/details(orderId=${o.id})}">view</a>
<!-- Will produce '/gtvg/order/details?orderId=3' (plus rewriting) -->
<a href="details.html" th:href="@{/order/details(orderId=${o.id})}">view</a>
<!-- Will produce '/gtvg/order/3/details' (plus rewriting) -->
<a href="details.html" th:href="@{/order/{orderId}/details(orderId=${o.id})}">view</a>
注意事项
th:href
是一个修饰符属性:一旦处理完毕,它将计算要使用的链接URL并将该值设置为该标记的href
属性<a>
。
<a href=""></a> 链接的属性可以省略不写。
- 我们被允许使用URL参数的表达式(如您所见
orderId=${o.id}
)。所需的URL参数编码操作也将自动执行。 - 如果需要几个参数,则用逗号分隔:
@{/order/process(execId=${execId},execType='FAST')}
- URL路径中也允许使用变量模板:
@{/order/{orderId}/details(orderId=${orderId})}
- 以
/
(例如:)开头的相对URL/order/details
将自动以应用程序上下文名称作为前缀。 - 如果cookie未启用或尚未知道,则
";jsessionid=..."
可能会向相对URL添加后缀,以便会话被保留。这就是所谓的URL重写,Thymeleaf允许你通过使用response.encodeURL(...)
Servlet API 的机制为每个URL 插入自己的重写过滤器。 - 该
th:href
属性允许我们(可选地)href
在我们的模板中有一个工作的静态属性,以便我们的模板链接在浏览器直接打开以供原型设计时保持可浏览的状态。
3.1.6、布尔表达式
布尔文字是true
和false
。例如:
<div th:if="${user.isAdmin()} == false"> ...
在这个例子中,这== false
是写在括号外,所以是Thymeleaf照顾它。如果它是写在花括号内,那么OGNL / SpringEL引擎将负责这个操作:
<div th:if="${user.isAdmin() == false}"> ...
3.1.7、算术运算符号
一些算术运算也可用:+
,-
,*
,/
和%
。
<div th:with="isEven=(${prodStat.count} % 2 == 0)">
请注意,这些运算符也可以在OGNL变量表达式中使用(在这种情况下,将由OGNL而不是Thymeleaf标准表达式引擎执行):
<div th:with="isEven=${prodStat.count % 2 == 0}">
请注意,其中一些运算符存在文本别名:div
(/
),mod
(%
)。
第四章:Iteration迭代输出
Iteration主要是用于迭代输出集合的数据,集合的类型有List、Set、Map、Collection等集合。
这个java.util.List
类不是唯一可用于Thymeleaf迭代的值。有一组相当完整的对象被认为可以被一个属性迭代th:each
:
- 任何对象的实现
java.util.Iterable
- 任何对象的实现
java.util.Enumeration
。 - 任何实现的对象
java.util.Iterator
,其值将被迭代器返回使用,而不需要缓存内存中的所有值。 - 任何对象的实现
java.util.Map
。当迭代映射时,iter变量将是类的java.util.Map.Entry
。 - 任何数组。
- 任何其他对象将被视为包含对象本身的单值列表。
4.1、使用th:each迭代
我们可以使用th:each来迭代输出模板的产品列表
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Good Thymes Virtual Grocery</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" media="all"
href="../../../css/gtvg.css" th:href="@{/css/gtvg.css}" />
</head>
<body>
<h1>Product list</h1>
<table>
<tr>
<th>NAME</th>
<th>PRICE</th>
<th>IN STOCK</th>
</tr>
<tr th:each="prod : ${prods}">
<td th:text="${prod.name}">Onions</td>
<td th:text="${prod.price}">2.41</td>
<td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
</tr>
</table>
<p>
<a href="../home.html" th:href="@{/}">Return to home</a>
</p>
</body>
</html>
4.2、th:each的状态变量
使用时th:each
,Thymeleaf提供了一个有用的机制来跟踪你的迭代状态:状态变量。
状态变量在一个th:each
属性中定义并包含以下数据:
- 当前迭代索引,从0开始。这是
index
属性。 - 当前迭代索引,从1开始。这是
count
属性。 - 迭代变量中的元素总数。这是
size
财产。 - 每个迭代的iter变量。这是
current
财产。 - 目前的迭代是偶数还是奇数。这些是
even/odd
布尔属性。 - 目前的迭代是否是第一个。这是
first
布尔属性。 - 目前的迭代是否是最后一个。这是
last
布尔属性。
<table>
<tr>
<th>NAME</th>
<th>PRICE</th>
<th>IN STOCK</th>
</tr>
<tr th:each="prod,iterStat : ${prods}" th:class="${iterStat.odd}? 'odd'">
<td th:text="${prod.name}">Onions</td>
<td th:text="${prod.price}">2.41</td>
<td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
</tr>
</table>
4.3、通过懒惰的数据检索进行优化
有时我们可能想要优化对数据集合的检索(例如从数据库),以便只有在真正要使用这些集合时才能检索这些集合。
这个变量可以在不知道其懒惰的情况下使用,代码如下:
<ul>
<li th:each="u : ${users}" th:text="${u.name}">user name</li>
</ul>
<ul th:if="${condition}">
<li th:each="u : ${users}" th:text="${u.name}">user name</li>
</ul>