它的特点便是:开箱即用,Thymeleaf允许您处理六种模板,每种模板称为模板模式:
- XML
- 有效的XML
- XHTML
- 有效的XHTML
- HTML5
- 旧版HTML5
所有这些模式都指的是格式良好的XML文件,但*Legacy HTML5*模式除外,它允许您处理HTML5文件,其中包含独立(非关闭)标记,没有值的标记属性或不在引号之间写入的标记属性。为了在这种特定模式下处理文件,Thymeleaf将首先执行转换,将您的文件转换为格式良好的XML文件,这些文件仍然是完全有效的HTML5(实际上是创建HTML5代码的推荐方法)[1](https://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf.html#fn1)。
另请注意,验证仅适用于XML和XHTML模板。
然而,这些并不是Thymeleaf可以处理的唯一模板类型,并且用户始终能够通过指定在此模式下*解析*模板的方法和*编写*结果的方式来定义他/她自己的模式。这样,任何可以建模为DOM树(无论是否为XML)的东西都可以被Thymeleaf有效地作为模板处理。
Springboot整合thymeleaf
使用springboot 来集成使用Thymeleaf可以大大减少单纯使用thymleaf的代码量,所以我们接下来使用springboot集成使用thymeleaf.
实现的步骤为:
- 创建一个sprinboot项目
- 添加thymeleaf的起步依赖
- 添加spring web的起步依赖
- 编写html 使用thymleaf的语法获取变量对应后台传递的值
- 编写controller 设置变量的值到model中
(1)创建工程
创建一个独立的工程springboot-thymeleaf,该工程为案例工程,不需要放到jwang-parent工程中。
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.jwang</groupId> <artifactId>springboot-thymeleaf</artifactId> <version>1.0-SNAPSHOT</version>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.4.RELEASE</version> </parent>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> </dependencies> </project>
|
(2)创建html
在resources中创建templates目录,在templates目录创建 demo1.html,代码如下:
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Thymeleaf的入门</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> </head> <body>
<p th:text="${hello}"></p> </body> </html>
|
解释:<html xmlns:th="http://www.thymeleaf.org">:这句声明使用thymeleaf标签
<p th:text="${hello}"></p>:这句使用 th:text="${变量名}" 表示 使用thymeleaf获取文本数据,类似于EL表达式。
(3)修改application.yml配置
创建application.yml,并设置thymeleaf的缓存设置,设置为false。默认加缓存的,用于测试。
spring: thymeleaf: cache: false
|
在这里,其实还有一些默认配置,比如视图前缀:classpath:/templates/,视图后缀:.html
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafProperties部分源码如下:

(4)控制层
创建controller用于测试后台 设置数据到model中。
创建com.jwang.controller.TestController,代码如下:
@Controller @RequestMapping("/test") public class TestController {
@RequestMapping("/hello") public String hello(Model model){ model.addAttribute("hello","hello welcome"); return "demo1"; } }
|
(5)测试
创建启动类com.jwang.ThymeleafApplication,代码如下:
@SpringBootApplication public class ThymeleafApplication {
public static void main(String[] args) { SpringApplication.run(ThymeleafApplication.class,args); } }
|
启动系统,并在浏览器访问
http://localhost:8080/test/hello
|

Thymeleaf基本语法
(1)th:href 后台代码
model.addAttribute("key1","value1"); model.addAttribute("url","/test/hello");
|
html:
<a th:href="@{${url}(key1=${key1},key2=${key1})}">去网站首页</a>
|
(2)th:each 遍历,功能类似jstl中的<c:forEach>标签。
创建com.jwang.model.User,代码如下:
public class User { private Integer id; private String name; private String address; }
|
Controller添加数据,List输出
@RequestMapping("/hello") public String hello(Model model){ model.addAttribute("hello","hello welcome");
List<User> users = new ArrayList<User>(); users.add(new User(1,"张三","深圳")); users.add(new User(2,"李四","北京")); users.add(new User(3,"王五","武汉")); model.addAttribute("users",users); return "demo1"; }
|
页面输出
<table> <tr> <td>id</td> <td>姓名</td> <td>地址</td> <td>下标</td> </tr> <tr th:each="abc,mystat:${users}"> <td th:text="${abc.id}"></td> <td th:text="${abc.name}">zhangsan</td> <td th:text="${abc.address}">深圳</td> <td th:text="${mystat.index+1}">深圳</td> </tr> </table>
|
测试效果

(3)Map输出 后台添加Map
Map<String,Object> dataMap = new HashMap<String,Object>(); dataMap.put("No","123"); dataMap.put("address","深圳"); model.addAttribute("dataMap",dataMap);
|
页面输出
<div th:each="map,mapStat:${dataMap}"> <div th:text="${map}"></div> key:<span th:text="${mapStat.current.key}"></span><br/> value:<span th:text="${mapStat.current.value}"></span><br/> </div>
|
或者:
<div th:each="entry:${dataMap}"> <div th:text="${entry}"></div> key:<span th:text="${entry.key}"></span><br/> value:<span th:text="${entry.value}"></span><br/> </div>
|
测试效果

(4)数组输出 后台添加数组
String[] names = {"张三","李四","王五"}; model.addAttribute("names",names);
|
页面输出
<div th:each="nm,nmStat:${names}"> <span th:text="${nmStat.count}"></span><span th:text="${nm}"></span> ============================================== </div>
|
测试效果

(5)Date输出
后台添加日期
model.addAttribute("now",new Date());
|
页面输出
<div> <span th:text="${#dates.format(now,'yyyy-MM-dd hh:ss:mm')}"></span> </div>
|
测试效果

(6)th:if条件
model.addAttribute("age",22);
|
页面输出
<div> <span th:if="${(age>=18)}">终于长大了!</span> </div>
|
测试效果

(7)使用javascript

java代码为:

(8) 字符拼接 使用||
后台代码:

模板:

canal监听生成静态页

如上图详情页的解决方案. 监听到数据的变化,直接调用feign 生成静态页即可.
需求分析
当商品微服务审核商品之后,应当发送消息,这里采用了Canal监控数据变化,数据变化后,调用feign实现生成静态页
Feign创建
在jwang-service-api中创建jwang-web-item-api,该工程中主要创建jwang-web-item的对外依赖抽取信息。
(1)Feign创建
在jwang-web-item-api中创建com.jwang.item.feign.PageFeign,代码如下:
@FeignClient(name="item") @RequestMapping("/page") public interface PageFeign {
@RequestMapping("/createHtml/{id}") Result createHtml(@PathVariable(name="id") Long id); }
|
(2)pom.xml依赖
修改jwang-service-canal工程的pom.xml,引入如下依赖:
<dependency> <groupId>com.jwang</groupId> <artifactId>jwang-web-item-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
|
(3)修改jwang-service-canal工程中的启动类

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class) @EnableEurekaClient @EnableCanalClient @EnableFeignClients(basePackages = {"com.jwang.content.feign","com.jwang.item.feign"}) public class CanalApplication {
public static void main(String[] args) { SpringApplication.run(CanalApplication.class, args); } }
|
canal监听数据变化
监听类中,监听商品数据库的tb_spu的数据变化,当数据变化的时候生成静态页或者删除静态页
在原来的监听类中添加如下代码即可,
@Autowired private PageFeign pageFeign;
@ListenPoint(destination = "example", schema = "jwang_goods", table = {"tb_spu"}, eventType = {CanalEntry.EventType.UPDATE, CanalEntry.EventType.INSERT, CanalEntry.EventType.DELETE}) public void onEventCustomSpu(CanalEntry.EventType eventType, CanalEntry.RowData rowData) {
if (eventType == CanalEntry.EventType.DELETE) { String spuId = ""; List<CanalEntry.Column> beforeColumnsList = rowData.getBeforeColumnsList(); for (CanalEntry.Column column : beforeColumnsList) { if (column.getName().equals("id")) { spuId = column.getValue(); break; } }
}else{ List<CanalEntry.Column> afterColumnsList = rowData.getAfterColumnsList(); String spuId = ""; for (CanalEntry.Column column : afterColumnsList) { if (column.getName().equals("id")) { spuId = column.getValue(); break; } } pageFeign.createHtml(Long.valueOf(spuId)); } }
|
整体的页面代码如下图所示已经实现:
