SpringBoot整合Thymeleaf

SpringBoot整合Thymeleaf

摘自https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html

一、thymeleaf简介

简介

简单说, Thymeleaf 是一个跟 Velocity、FreeMarker 类似的模板引擎,它可以完全替代 JSP 。相较与其他的模板引擎,它有如下三个极吸引人的特点:

模板引擎(这里特指用于Web开发的模板引擎)是为了使[用户界面](https://baike.baidu.com/item/用户界面)与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的[HTML](https://baike.baidu.com/item/HTML)文档

· 1.Thymeleaf 在有网络和无网络的环境下皆可运行,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果。这是由于它支持 html 原型,然后在 html 标签里增加额外的属性来达到模板+数据的展示方式。浏览器解释 html 时会忽略未定义的标签属性,所以 thymeleaf 的模板可以静态地运行;当有数据返回到页面时,Thymeleaf 标签会动态地替换掉静态内容,使页面动态显示。

· 2.Thymeleaf 开箱即用的特性。它提供标准和spring标准两种方言,可以直接套用模板实现JSTL、 OGNL表达式效果,避免每天套模板、改jstl、改标签的困扰。同时开发人员也可以扩展和创建自定义的方言。

· 3.Thymeleaf 提供spring标准方言和一个与 SpringMVC 完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能。

为什么使用 Thymeleaf

如果希望以 Jar 形式发布模块则尽量不要使用 JSP 相关知识,这是因为 JSP 在内嵌的 Servlet 容器上运行有一些问题 (内嵌 Tomcat、 Jetty 不支持 Jar 形式运行 JSP,Undertow 不支持 JSP)。

Spring Boot 官方中推荐使用 Thymeleaf 作为模板引擎,因为 Thymeleaf 提供了完美的 Spring MVC 支持

Spring Boot 提供了大量模板引擎,包括:
FreeMarker
Groovy
Mustache
Thymeleaf
Velocity
Beetl

官网:https://www.thymeleaf.org/

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IXjkRf9R-1618548158522)(http://m.qpic.cn/psb?/V13x1ZYF1dFQtq/vJkN8hHnPA4E7zakqBxOmJK68PWcYgGb2arpE2il14c!/b/dL4AAAAAAAAA&bo=sAXHAgAAAAADB1I!&rf=viewer_4)]

二、第一个Thymeleaf

1、工具创建SpringBoot项目

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eQnbLtJR-1618548158526)(http://m.qpic.cn/psb?/V13x1ZYF1dFQtq/oLBANxXFzwb.gw1bvu.B1DmRIRb24ckYZIe26G.wfks!/b/dFIBAAAAAAAA&bo=qARCAwAAAAADF98!&rf=viewer_4)]

2、pom.xml

引入依赖

主要增加 spring-boot-starter-thymeleaf 和 nekohtml 这两个依赖
spring-boot-starter-thymeleaf:Thymeleaf 自动配置
nekohtml:允许使用非严格的 HTML 语法

NekoHTML 是一个简单地HTML扫描器和标签补偿器(tag balancer) ,
使得程序能解析HTML文档并用标准的XML接口来访问其中的信息。
这个解析器能投扫描HTML文件并“修正”许多作者(人或机器)在编写HTML文档过程中常犯的错误。
NekoHTML 能增补缺失的父元素、自动用结束标签关闭相应的元素,以及不匹配的内嵌元素标签。
  <!-- 支持非严格语法的neko -->
        <dependency>
            <groupId>net.sourceforge.nekohtml</groupId>
            <artifactId>nekohtml</artifactId>
            <version>1.9.22</version>
        </dependency>
  <!-- thymeleaf -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

完整版如下:

 <dependencies>

        <!-- spring web mvc-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- spring mybatis -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.0</version>
        </dependency>
        <!-- mysql 驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!-- druid 数据源连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>

        <!-- 热部署 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!-- thymeleaf -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <!-- 支持非严格语法的neko -->
        <dependency>
            <groupId>net.sourceforge.nekohtml</groupId>
            <artifactId>nekohtml</artifactId>
            <version>1.9.22</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

3、application.yml

#server config info
server:
  port: 8080

spring:
#datasource connect info
  datasource:
    name: test
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      url: jdbc:mysql://localhost:3306/maven_ssm?serverTimezone=GMT%2B8
      driver-class-name: com.mysql.cj.jdbc.Driver
      username: root
      password: root
      filters: stat
      initial-size: 1
      min-idle: 1
      max-active: 20
      max-wait: 60000
      time-between-eviction-runs-millis: 60000

      min-evictable-idle-time-millis: 300000
      validation-query: SELECT 'x'
      test-while-idle: true
      test-on-borrow: false
      test-on-return: false

      pool-prepared-statements: false
      max-pool-prepared-statement-per-connection-size: 20


# mybatis config info
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.qfjy.bean

4、SpringBoot支持Thymeleaf

查看源代码:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q5bHdplC-1618548158529)(http://m.qpic.cn/psb?/V13x1ZYF1dFQtq/sPa36mIuPLXlKFvwx08puneL5xYKA1iAPCzYH1.v9vY!/b/dL8AAAAAAAAA&bo=zAX3AQAAAAADFw0!&rf=viewer_4)]

只需要将开发页面放到Thymeleaf /templates/***.html即可直接访问

5、yml文件中配置Thymeleaf

添加如下自定义配置:(其它默认即可)

cache: false #开发阶段建议关闭缓存

mode: LEGACYHTML5 #用非严格的HTML5 默认是HTML5

如果不想对标签进行严格的验证,使用spring.thymeleaf.mode=LEGCYHTML5去掉验证,同时需要引入NekoHTML包

spring:
  thymeleaf:
    encoding: UTF-8  #编码规范 默认
    cache: false #开发阶段建议关闭缓存
    prefix: classpath:/templates/ 
    suffix: .html
    mode: LEGACYHTML5 #用非严格的HTML5 默认是HTML5
    servlet:
      content-type: text/html

6、创建html页面

在 templates 目录下创建 index.html 文件,

修改 html 标签用于引入 thymeleaf 引擎,这样才可以在其他标签里使用 th:* 语法,声明如下:

<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<html  xmlns:th="http://www.thymeleaf.org">

代码如下:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
    模版引擎主页的HTML页面
    <p th:text="${msg}">信息显示</p>
</body>
</html>

7、controller

@RequestMapping("index")
@Controller
public class IndexController {
    @RequestMapping("index")
    public String index(Model model){
        model.addAttribute("msg","我的第一个信息");
        model.addAttribute("author","guoweixin");
        return "index"; //基于约定优于配置,默认会到 /templates/  .html
    }
}

8、访问请求即可

备注:SpringBoot使用thymeleaf作为视图展示,约定将模板文件放置在src/main/resource/templates目录下,静态资源放置在static目录下

小提示:

templates文件夹,是放置模板文件的,因此需要视图解析器来解析它。所以必须通过服务器内部进行访问,也就是要走控制器–服务–视图解析器这个流程才行。

如果想直接访问html页面,可放置到静态资源下/public….

三、Thymeleaf常用语法

1、引入 Thymeleaf

修改 html 标签用于引入 thymeleaf 引擎,这样才可以在其他标签里使用 th:* 语法,这是下面语法的前提。

<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">

知识点补充:

xmlns属性 是用来定义xml namespace(命名空间)的。该属性可以放置在文档内任何元素的开始标签中。该属性的值类似于 URL,它定义了一个命名空间,浏览器会将此命名空间用于该属性所在元素内的所有内容。如果需要使用符合 XML 规范的 XHTML 文档,则应该在文档中的<html> 标签中至少使用一个 xmlns 属性,以指定整个文档所使用的主要命名空间。不过即使你的 XHTML 文档没有使用此属性,W3C 的验证器也不会报错。因为 "xmlns=http://www.w3.org/1999/xhtml" 是一个固定值,所以,即使你没有包含它,此值也会被添加到 <html> 标签中。

2、th:text 变量表达式

th:text 标准/选择变量表达式

标准变量表达式

语法:${…}

标准变量表达式

获取变量值用 $ 符号,对于javaBean的话使用变量名.属性名方式获取,这点和 EL 表达式一样.

    <p th:text="${msg}">信息显示</p>
    <p th:text="${weixin.name}">姓名</p>

另外 $ 表达式只能写在th标签内部,不然不会生效,上面例子就是使用 th:text 标签的值替换 p 标签里面的值,至于 p 里面的原有的值只是为了给前端开发时做展示用的.这样的话很好的做到了前后端分离

选择变量表达式

选择变量表达式 或 *号变量表达式

前端测试代码:(对象的获取方式)

    <div th:object="${user}">
        <p th:text="*{name}">姓名</p>
        <p th:text="*{telphone}">手机号码</p>
    </div>

3、th:utext

这是th:text属性的默认行为。如果我们希望Thymeleaf尊重我们的HTML标签而不是逃避它们,我们将不得不使用不同的属性:( th:utext对于“未转义的文本”)

Controller代码:

        model.addAttribute("msg1","<h2>普通字符串</h2>");
        model.addAttribute("msg2","<h2>普通字符串</h2>");

Html代码:

<span th:text="你好${msg1}">测试1</span>
<span th:utext="${msg2}">测试2</span>

练习:显示当前个人信息、当前的日期等功能。

4 字符串拼接

字符串拼接操作单引号:

<span th:text="'我的字符串数据:'+${msg1}">数据</span>

更简洁的方式是:|…|

<span th:text="|我的字符串数据${msg1}|">数据</span>

5. URL表达式th:href

Thymeleaf对于 URL 的处理是通过语法 @{…} 来处理的

访问页面:<br/>
<a href="/404.html">404.html</a>
<a href="/index/index"  th:href="@{|/index/index?a=21&b=${msg1}|}" >查看标签</a>

访问URL路径:

观察

例:(项目的上下文 /)例:(加项目上下文/boot)

**thymeleaf th:href /**时会帮我们加上上下文路径

建议所有thymeleaf路径使用:绝对路径(**用@{}**拼接)

静态页面用相对路径进行匹配

练习功能:完成页面间跳转流程

6、行内编写

虽然标准方言允许我们使用标记属性来完成几乎所有操作,但在某些情况下我们可能更喜欢将表达式直接编写到HTML文本中。例如,我们可能更喜欢这样写:

<p>Hello, [[${session.user.name}]]!</p>

…而不是这个:

<p>Hello, <span th:text="${session.user.name}">Sebastian</span>!</p>

官方文档:https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#expression-inlining

四、Thymeleaf 常用属性

1、 th:each

常用标签,类似于JSTL中的<c:forEach>,该属性循环遍历集合、数组或Map

 <tr th:each="u:${list}">
        <td th:text="${uStat.count}">ID</td>
        <td th:text="${u.name}">姓名</td>
        <td th:text="${u.telphone}">手机号</td>
        <td th:text="${u.status}">状态</td>
        <td>操作</td>
    </tr>
${list}是后台传过来的key
u是${list}定义遍历名称
uStat是循环体的信息。默认是 名称+stat,同时也可以自定义名称,中间以,号分隔。
   th:each="u,i:${list}"
循环体可以获取如下信息:
  index 当前迭代对象的index(0)开始
  size 迭代对象大小
  count(从1开始)
  current(当前迭代变量)
  even/odd 布尔值(是否是偶数/奇数  0开始)
  first 布尔值 是否是第一个
  last 布尔值 是否是最后一个

2、 th:if

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U2hoVHWB-1618548158532)(http://m.qpic.cn/psb?/V13x1ZYF1dFQtq/IpiJORbFwVoD97r2xMxDyVy9BeYa3fTk08NofZWCQnU!/b/dMMAAAAAAAAA&bo=8QLXAAAAAAADFxY!&rf=viewer_4)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yMkJaB9n-1618548158534)(http://m.qpic.cn/psb?/V13x1ZYF1dFQtq/XAXHvAqAYHKn*8GTPCNeyDD29vJ4k3yYw4oCFIUDUmI!/b/dL4AAAAAAAAA&bo=6gLNAAAAAAADFxc!&rf=viewer_4)]

3、 th:switch case

 <h1>switch示例</h1>
    <div th:switch="${sex}">
        <span th:case="1">男</span>
        <span th:case="2">女</span>
        <span th:case="3">其它</span>
        <span th:case="*">未知</span>
    </div>

4、 th:src

用于外部资源引入,例如

图片:
<img src="/images/1.jpg" th:src="@{/images/1.jpg}" />
外部JS文件:
<script type="text/javascript" src="js/jquery.min.js" th:src="@{/js/popup.js}"></script>

5、th:value

思考如下代码:input输入框:

<input type="text" th:text="${msg}"/>
<input type="text" th:text="${msg}" th:value="${msg}"/>

6、th:attr

该属性用于给某元素的属性进行赋值

可以通过该属性为某个name赋动态名称

给 value赋值
<input type="text"  th:attr="value=${msg}" />
给 name赋值
<input type="text"  th:attr="name=${msg}" />

五、Thymeleaf其它 th 标签

th:abbr

th:accept

th:accept-charset

th:accesskey

th:action

th:align

th:alt

th:archive

th:audio

th:autocomplete

th:axis

th:background

th:bgcolor

th:border

th:cellpadding

th:cellspacing

th:challenge

th:charset

th:cite

th:class

th:classid

th:codebase

th:codetype

th:cols

th:colspan

th:compact

th:content

th:contenteditable

th:contextmenu

th:data

th:datetime

th:dir

th:draggable

th:dropzone

th:enctype

th:for

th:form

th:formaction

th:formenctype

th:formmethod

th:formtarget

th:frame

th:frameborder

th:headers

th:height

th:high

th:href

th:hreflang

th:hspace

th:http-equiv

th:icon

th:id

th:keytype

th:kind

th:label

th:lang

th:list

th:longdesc

th:low

th:manifest

th:marginheight

th:marginwidth

th:max

th:maxlength

th:media

th:method

th:min

th:name

th:optimum

th:pattern

th:placeholder

th:poster

th:preload

th:radiogroup

th:rel

th:rev

th:rows

th:rowspan

th:rules

th:sandbox

th:scheme

th:scope

th:scrolling

th:size

th:sizes

th:span

th:spellcheck

th:src

th:srclang

th:standby

th:start

th:step

th:style

th:summary

th:tabindex

th:target

th:title

th:type

th:usemap

th:value

th:valuetype

th:vspace

th:width

th:wrap

th:xmlbase

th:xmllang

th:xmlspace

th:alt-title

th:lang-xmllang

六、完成增删改查功能

列表list.html:

<table align="center" width="800px" border="1">
    <tr>
        <td>编号</td>
        <td>用户名</td>
        <td>密码</td>
        <td>状态</td>
        <td>操作</td>
    </tr>
    <tr th:each="u,i:${list}">
        <td th:text="${i.count}">编号</td>
        <td th:text="${u.uname}">用户名</td>
        <td th:text="${u.upass}">密码</td>
        <td >
            <div th:switch="${u.status}">
                <span th:case="1">有效</span>
                <span th:case="0">无效</span>
                <span th:case="*">待定</span>
            </div>
        </td>
        <td>
            <a href="">添加</a>
            <a href="">修改</a> 
            <a href="view.html" th:href="@{|/user/${u.id}|}">查询</a>
            <a href="javascript:del(1)" th:href="|javascript:del('${u.id}')|">删除</a> 
        </td>
    </tr>

</table>

ajax删除:

 function del(id){
            $.ajax({
                type:"post",
                // user/del?id=id
                url:'[[@{/user/del}]]',  //请求的URL要注意用@{}
                data:{"id":id},
                success:function(msg){
                    window.location.href="[[@{/user/all}]]"  //请求的URL要注意用@{}
                }
            })
        }

统一错误异常处理

演示

Spring Boot提供了一个默认的映射:/error,当处理中抛出异常之后,会转到该请求中处理,并且该请求有一个全局的错误页面用来展示异常内容。

@Controller
public class DemoController {
    @RequestMapping("info")
    public String info(){
        System.out.println(1/0);
        return "ok";
    }
}

可以看到类似下面的报错页面,该页面就是Spring Boot提供的默认error映射页面。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5927e48S-1618548158535)(img\1.png)]

统一异常处理

在resource/templates下添加error.html页面,

springBoot会自动找到该页面作为错误页面,适合内嵌Tomcat或者war方式。

在web/servlert/error下:

ErrorMvcAutoConfiguration类

SpringBoot错误视图提供了以下错误属性:

timestamp:错误发生时间;
status:HTTP状态码;
error:错误原因;
exception:异常的类名;
message:异常消息(如果这个错误是由异常引起的);
errors:BindingResult异常里的各种错误(如果这个错误是由异常引起的);
trace:异常跟踪信息(如果这个错误是由异常引起的);
path:错误发生时请求的URL路径。

状态码具体描述:
https://www.runoob.com/http/http-status-codes.html

SpringBoot使用的前端框架模板不同,页面的名称也有所不同:

实现Spring的View接口的Bean,其ID需要设置为error(由Spring的BeanNameViewResolver所解析);
如果配置了Thymeleaf,则需命名为error.html的Thymeleaf模板;
如果配置了FreeMarker,则需命名为error.ftl的FreeMarker模板;
如果配置了Velocity,则需命名为error.vm的Velocity模板;
如果是用JSP视图,则需命名为error.jsp的JSP模板。

在resource/templates/下添加error.html页面

显示全局显示的错误页面。

(error替换成对应的错误码,404、401、500等,还可以用4xx、5xx等),

springBoot会自动找到该页面作为错误页面,需要将该页面放到 templates/error/4xx.html 下

templates
  error.html  //默认全局错误页面
  error		  //文件目录
    4xx.html  //对应错误码页面
    5xx.html
上一篇:Thymeleaf入门


下一篇:POJ 3368