01、Thymeleaf
       官网地址:Thymeleaf https://www.thymeleaf.org/
https://www.thymeleaf.org/ 
  https://www.thymeleaf.org/
https://www.thymeleaf.org/  
 简介
         Thymeleaf是一种服务器端Java模板引擎,用于将数据渲染为HTML、XML、JavaScript等格式,并在Web浏览器中呈现给用户。 具体来说,Thymeleaf充当着视图层的角色,与控制器和模型一起构成了典型的MVC(模型-视图-控制器)设计模式中的视图部分。 Thymeleaf模板引擎允许我们在模板中使用HTML标记、JavaScript表达式和Thymeleaf表达式等,以动态地生成Web页面。Thymeleaf提供了一些特殊的属性和标签,以支持与控制器和模型之间的数据绑定和交互。 
        相比于传统的前端技术(如HTML、CSS和JavaScript),Thymeleaf更注重后端的处理逻辑和数据交互。Thymeleaf能够从服务器端动态地生成页面,这意味着我们可以将服务器端的数据直接渲染到页面上,从而减少了大量的前端开发工作。同时,由于Thymeleaf能够与后端Java代码无缝集成,因此我们可以很方便地使用Java提供的各种类库和框架,进一步简化了开发工作。 
   为什么使用thymeleaf ?
     因为jsp页面存在劣势,它的本质是Servlet,还是一个类,只要是类就离不开JVM。我们无法通过浏览器直接查看JSP页面的效果,这不便于前端页面的实现。 
       替代JSP: 
          1、模板引擎,具备JSP的功能,但是比JSP更加强大,可以直接通过浏览器查看页面效果。 
          2、前后端分离,Vue。 
  简介Thymeleaf 的特点
-  动静结合:Thymeleaf 既可以直接使用浏览器打开,查看页面的静态效果,也可以通过 Web 应用程序进行访问,查看动态页面效果。
-  开箱即用:Thymeleaf 提供了 Spring 标准方言以及一个与 SpringMVC 完美集成的可选模块,可以快速地实现表单绑定、属性编辑器、国际化等功能。
-  与 SpringBoot 完美整合:SpringBoot 为 Thymeleaf 提供了的默认配置,并且还为 Thymeleaf 设置了视图解析器,因此 Thymeleaf 可以与 Spring Boot 完美整合。
 Thymeleaf 通过在 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="${username}">Original Value</p></body></html>
02、物理视图和逻辑视图
2.1、物理视图
         请求转发到一个HTML页面时,使用的完整的转发路径就是物理视图。 
              例如:/pages/user/index.html 
           如果我们把所有的HTML页面都放在某个统一的目录下,那么转发地址就会呈现出明显的规律: 
              /pages/user/login.html 
              /pages/user/login_success.html 
              /pages/user/regist.html 
              /pages/user/regist_success.html 
           规律:路径的开头都是:/pages/user/  ,路径的结尾都是:.html  
           所以,路径开头的部分我们称之为视图前缀,路径结尾的部分我们称之为视图后缀。 
  2.2、逻辑视图
         物理视图=视图前缀+逻辑视图+视图后缀 
 |  视图前缀  |  逻辑视图  |  视图后缀  |  物理视图  | 
|  /pages/user/  |  login  |  .html  |  /pages/user/login.html  | 
|  /pages/user/  |  login_success  |  .html  |  /pages/user/login_success.html  | 
03、Thymeleaf 语法
3.1、引入命令空间
<!DOCTYPE HTML><html xmlns:th="http://www.thymeleaf.org"><head><title>Index Page</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /></head><body><p th:text="${message}">Welcome to BeiJing!</p></body></html>
 注意:‘xmlns:th="http://www.thymeleaf.org"’引入Thymeleaf命名空间。 
  3.2、常用标签
3.2.1、th:text
        作用:替换标签的文本原始值。 
 <!-- 使用【字面量值】替换标签体原始值--><h1 th:text="HelloWorld">标签体原始值</h1><!-- 使用域中数据替换标签体原始值 --><h1 th:text="${username}">这里要显示一个动态的username</h1>
3.2.2、th:属性名
         作用:替换指定属性的属性值 
 <input type="text" name="username" th:value="${username}"/>
3.3、常用表达式
|  语法  |  描述  |  作用  | 
|  ${...}  |  变量表达式  |  变量表达式 是最常用的一种表达式,它主要可以获取变量的值。  | 
|  *{...}  |  选择表达式  |  消息表达式 主要是用于读取属性文件(.properties)中的值,它常常用于国际化。  | 
|  #{...}  |  消息表达式  |  选择表达式 我们也称为是星号表达式,它与 变量表达式 的区别是:变量表达式 的对象取的是整个上下文中的变量,而 选择表达式 的对象取的是当前对象中的变量。这样做的好处是只需要在当前对象中取,不需要通过上下文去取,在一定程度上提高了执行效率,这也是性能上的一种优化。  | 
|  @{...}  |  链接表达式  |  链接表达式 主要在页面中有链接的地方使用。  | 
|  ~{...}  |  分段表达式  |  分段表达式 主要用于模板布局时的引用。也就是在一个页面中引入另一个页面中的内容。  | 
3.3.1、案例
     1)、变量表达式 
 <!-- 获取 name 变量的值 --><p th:text="${name}"></p>
     2)、选择表达式 
 <!-- book 中从上下文中取的一个变量 --><div th:object="${book}">
<!-- title 是 book 中的属性 --><span th:text="*{title}"></span> </div>
     其中 th:object 的意思是:用来接受后台传过来的对象。 
       3)、消息表达式 
 <!-- 读取属性文件中 key 为 name 的值 --><p th:text="#{name}"></p>
     注意: 我们必须先要配置属性文件所在位置,在项目配置文件中配置以下内容: 
 spring:messages:basename: msg
     4)、链接表达式 
 
<a th:href="@{/result}">...</a><!--整个页面 href和src属性的标签自动拼接项目地址 http://ip:端口/项目名/ --><base th:href="@{/}" th:src="@{/}">
     5)、分段表达式 
 
     首先我们准备两个页面,分别是 result.html 和 foot.html,我们在 result.html 中引入 foot.html 的内容。 
 
 
     result.html 
 
<body><p>这是 result.html 页面</p><div th:insert="~{foot :: copy}"></div></body>foot.html<body><div th:fragment="copy">© 2020 <a href="http://www.baidu.com">百度</a></div></body>
3.4、内置对象
     所谓内置对象其实就是在Thymeleaf的表达式中可以直接使用的对象。 
 
 基本对象: 
 |  对象  |  描述  | 
|  #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  | 
 工具类对象: 
 
| 对象 |  描述  | 
|  #dates  |  日期时间工具类  | 
|  #strings  |  字符串工具类  | 
|  #lists  |  List集合工具类  | 
|  #numbers  |  数字工具类  | 
|  #calendars  |  日历工具类  | 
|  #objects  |  对象工具类  | 
|  #bools  |  布尔工具类  | 
|  #arrays  |  数组工具类  | 
|  #sets  |  Set工具类  | 
|  #maps  |  Map工具类  | 
 处理空值, 通过加问号来判断前面的值是否为空,防止报错。 
 
<p th:text="${data?.name}"></p>
 示例: 
 
 
     #ctx 
 
<!-- zh_CN --><p th:text="${#ctx.getLocale()}"></p><!-- Welcome to BeiJing! --><p th:text="${#ctx.getVariable('message')}"></p><!-- true --><p th:text="${#ctx.containsVariable('message')}"></p>
     #vars 
 
<!-- zh_CN --><p th:text="${#vars.getLocale()}"></p><!-- Welcome to BeiJing! --><p th:text="${#vars.getVariable('message')}"></p><!-- true --><p th:text="${#vars.containsVariable('message')}"></p>
     #locale 
 
<!-- zh_CN --><p th:text="${#locale}"></p><!-- CN --><p th:text="${#locale.country}"></p><!-- 中国 --><p th:text="${#locale.displayCountry}"></p><!-- zh --><p th:text="${#locale.language}"></p><!-- 中文 --><p th:text="${#locale.displayLanguage}"></p><!-- 中文 (中国) --><p th:text="${#locale.displayName}"></p>
     #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><!-- /standard-expression-syntax/variables --><p th:text="${#request.requestURI}"></p><!-- http://localhost:8080/standard-expression-syntax/variables --><p th:text="${#request.requestURL}"></p><!-- /standard-expression-syntax/variables --><p th:text="${#request.servletPath}"></p><!-- java.util.Collections$3@203646fe --><p th:text="${#request.parameterNames}"></p><!-- {q=[Ljava.lang.String;@3308c69f} --><p th:text="${#request.parameterMap}"></p><!-- q=expression --><p th:text="${#request.queryString}"></p>
     注意,请求地址的 URL 参数直接通过#request.x是取不出来的,需要使用param.x语法来取出。如,URL:/standard-expression-syntax/variables?q=expression,取出 q 参数的正确方式: 
 
<p th:text="${param.q}"></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 
 
<!-- 2BCB2A0EACFF2D9D249D9799431B5127 --><p th:text="${#session.id}"></p><!-- 1499786693244 --><p th:text="${#session.lastAccessedTime}"></p><!-- fanlychie --><p th:text="${#session.getAttribute('user').name}"></p>
     注意,放到会话里面的对象直接通过#session.x是取不出来的,需要使用session.x语法来取出。如,取出会话里面的 user 对象的正确方式: 
 
<p th:text="${session.user.name}"></p>
     #dates 
 
<!--2022年9月18日 GMT+08:00 下午1:40:48--><p th:text="${#dates.format(myDate)}"></p><!--2022-09-18--><p th:text="${#dates.format(myDate, 'yyyy-MM-dd')}"></p><!--2022-09-18 13:40:48--><p th:text="${#dates.format(myDate, 'yyyy-MM-dd HH:mm:ss')}"></p><!--2022--><p th:text="${#dates.year(myDate)}"></p><!--9--><p th:text="${#dates.month(myDate)}"></p><!--Sun Sep 18 13:40:49 GMT+08:00 2022--><p th:text="${#dates.createNow()}"></p>
     #strings 
 
<!--HELLO WORLD--><p th:text="${#strings.toUpperCase(myStr)}"></p><!--2--><p th:text="${#strings.indexOf(myStr,'ll')}"></p><!--llo--><p th:text="${#strings.substring(myStr, 2, 5)}"></p><!--hello worldJava--><p th:text="${#strings.concat(myStr, 'Java')}"></p><!--11--><p th:text="${#strings.length(myStr)}"></p><!--5--><p th:text="${#strings.length('happy')}"></p><!--true--><p th:text="${#strings.contains(myStr, 'hello')}"></p>
     #lists 
 
<!--3--><p th:text="${#lists.size(myList)}"></p><!--true--><p th:text="${#lists.contains(myList, 1)}"></p><!--false--><p th:text="${#lists.isEmpty(myList)}"></p><!--[1, 2, 3]--><p th:text="${#lists.sort(myList)}"></p>
     #numbers 
 
<!--¥12.25--><p th:text="${#numbers.formatCurrency(myNumber)}"></p><!--0012.2--><p th:text="${#numbers.formatDecimal(myNumber, 4, 1)}"></p>
3.4、字符串拼接
      在Thymeleaf中,可以使用+运算符进行字符串拼接。例如: 
 
<p th:text="'Hello, ' + ${user.name} + '!'">默认问候</p>
3.5、条件比较
      Thymeleaf支持常见的条件比较,如==、!=、<、>等。例如: 
 
<div th:if="${user.age} > 18">成年用户</div>
3.6、switch多分支
      Thymeleaf支持switch语句,用于多分支条件判断。例如: 
 
<div th:switch="${user.role}"><p th:case="'admin'">管理员</p><p th:case="'user'">普通用户</p><p th:case="*">未知角色</p></div>
3.7、循环
      Thymeleaf支持th:each属性,用于遍历集合。例如: 
 
<ul><li th:each="item : ${items}" th:text="${item.name}">默认列表项</li></ul>
3.8、逻辑运算符
      在Thymeleaf中,我们可以使用加(+)、减(-)、乘(*)、除(/)和取余(%)等基本算术运算符来进行数值计算。这些运算符的使用方法与传统的编程语言类似,可以直接应用在表达式中,实现数值的加减乘除等操作。 例如: 
 
<p th:text="${user.age} + 1">年龄加一</p>
3.9、内联
     Thymeleaf支持内联表达式,用于在文本和属性中直接插入表达式。这种表达式允许我们在文本内容和HTML属性中直接插入动态数据,从而实现页面内容的灵活定制。例如: 
 
<p>你好,[[${user.name}]]!</p>
04、Thymeleaf 与 springboot整合
4.1、导入依赖
<!--thymeleaf--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency>
4.2、页面引入命名空间
xmlns:th="http://www.thymeleaf.org"
 到这里页面就可以使用thymeleaf的语法,注意:页面要经过控制器。 
 
 
4.3、静态资源项目名直接访问
     添加配置 
 
 #开放静态资源目录,这个配置目录会覆盖默认配置:"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/" 
 spring:resources:static-locations: classpath:/static/,file:${file.dir}#资源目录file:#资源根目录dir: D:/data
     这样D盘的data目录下的资源直接可以使用:http://IP地址:端口/资源名 
 
