Thymeleaf教程(10分钟入门)

Thymeleaf教程(10分钟入门)

Thymeleaf 是一款用于渲染 XML/XHTML/HTML5 内容的模板引擎。它与 JSP,Velocity,FreeMaker 等模板引擎类似,也可以轻易地与 Spring MVC 等 Web 框架集成。与其它模板引擎相比,Thymeleaf 最大的特点是,即使不启动 Web 应用,也可以直接在浏览器中打开并正确显示模板页面 。

一. Thymeleaf 简介

Thymeleaf 是新一代 Java 模板引擎,与 Velocity、FreeMarker 等传统 Java 模板引擎不同,Thymeleaf 支持 HTML 原型,其文件后缀为“.html”,因此它可以直接被浏览器打开,此时浏览器会忽略未定义的 Thymeleaf 标签属性,展示 thymeleaf 模板的静态页面效果;当通过 Web 应用>程序访问时,Thymeleaf 会动态地替换掉静态内容,使页面动态显示。
Thymeleaf 通过在 html 标签中,增加额外属性来达到“模板+数据”的展示方式,示例代码如下。

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--th:text 为 Thymeleaf 属性,用于在展示文本-->
<h1 th:text="迎您来到Thymeleaf">欢迎您访问静态页面 HTML</h1>
</body>
</html>

当直接使用浏览器打开时,浏览器展示结果如下。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9nSkOlHl-1657013815619)(C:\Users\fm016\Desktop\新建文件夹\新建文件夹\1.png)]

当通过 Web 应用程序访问时,浏览器展示结果如下。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pmund1OJ-1657013815621)(C:\Users\fm016\Desktop\新建文件夹\新建文件夹\2.png)]

Thymeleaf 的特点

Thymeleaf 模板引擎具有以下特点:

  • 动静结合:Thymeleaf 既可以直接使用浏览器打开,查看页面的静态效果,也可以通过 Web 应用程序进行访问,查看动态页面效果。
  • 开箱即用:Thymeleaf 提供了 Spring 标准方言以及一个与 SpringMVC 完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能。
  • 多方言支持:它提供了 Thymeleaf 标准和 Spring 标准两种方言,可以直接套用模板实现 JSTL、 OGNL 表达式;必要时,开发人员也可以扩展和创建自定义的方言。
  • 与 SpringBoot 完美整合:SpringBoot 为 Thymeleaf 提供了的默认配置,并且还为 Thymeleaf 设置了视图解析器,因此 Thymeleaf 可以与 Spring Boot 完美整合。

二. Thymeleaf 语法规则

在使用 Thymeleaf 之前,首先需要导入thymeleaf依赖,然后在页面的 html 标签中声明名称空间,示例代码如下。

<!-- thymeleaf依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<html xmlns:th="http://www.thymeleaf.org">
    
</html>

在 html 标签中声明此名称空间,可避免编辑器出现 html 验证错误,但这一步并非必须进行的,即使我们不声明该命名空间,也不影响 Thymeleaf 的使用。

Thymeleaf 作为一种模板引擎,它拥有自己的语法规则。Thymeleaf 语法分为以下 2 类:

  • 标准表达式语法
  • th 属性

2.1 基础语法

2.1.1 变量表达式 ${}

使用方法:直接使用 th:xx = “${}” 获取对象属性。例如:

<form id="userForm">
    <input id="id" name="id" th:value="${user.id}"/>
    <input id="username" name="username" th:value="${user.username}"/>
    <input id="password" name="password" th:value="${user.password}"/>
</form>

<div th:text="hello"></div>

<div th:text="${user.username}"></div>

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oZ7ta3MD-1657013815622)(C:\Users\fm016\Desktop\新建文件夹\新建文件夹\3.png)]

2.1.2 选择变量表达式 *{}

使用方法:首先通过th:object 获取对象,然后使用th:xx = "*{}"获取对象属性。
这种简写风格极为清爽,推荐大家在实际项目中使用。 例如:

<form id="userForm" th:object="${user}">
    <input id="id" name="id" th:value="*{id}"/>
    <input id="username" name="username" th:value="*{username}"/>
    <input id="password" name="password" th:value="*{password}"/>
</form>

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cUVQ0wMT-1657013815623)(C:\Users\fm016\Desktop\新建文件夹\新建文件夹\4.png)]

2.1.3 链接表达式 @{}

使用方法:通过链接表达式@{}直接拿到应用路径,然后拼接静态资源路径。例如:

<script th:src="@{jquery/jquery-1.10.2.min.js}"></script>
<link th:href="@{bootstrap/css/bootstrap.css}" rel="stylesheet" type="text/css">

2.1.4 片段表达式 ~{}

片段表达式是Thymeleaf的特色之一,细粒度可以达到标签级别,这是JSP无法做到的。
片段表达式拥有三种语法:

  • ~{ viewName } 表示引入完整页面
  • ~{ viewName ::selector} 表示在指定页面寻找片段 其中selector可为片段名、jquery选择器等
  • ~{ ::selector} 表示在当前页寻找
    使用方法:首先通过th:fragment定制片段 ,然后通过th:replace 填写片段路径和片段名。例如:
<!-- comm.html-->
<head th:fragment="page">
    <scrpit th:src="@{jquery/jquery-1.10.2.min.js}"></scrpit>
</head>
<body>
    <h1>这是引入完整的页面</h1>
</body>

<!-- demo01.html -->
<div th:replace="~{comm}"></div>

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Nqnmgtq2-1657013815623)(C:\Users\fm016\Desktop\新建文件夹\新建文件夹\5.png)]

<!-- comm.html-->
<head th:fragment="page">
    <scrpit th:src="@{jquery/jquery-1.10.2.min.js}"></scrpit>
</head>

<!-- demo01.html -->
<div th:replace="~{comm::page}"></div>

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XDAr5URE-1657013815624)(C:\Users\fm016\Desktop\新建文件夹\新建文件夹\6.png)]

在实际使用中,我们往往使用更简洁的表达,去掉表达式外壳直接填写片段名。例如:

<!-- demo01.html -->
<div th:replace="comm::page"></div>

值得注意的是,使用替换路径th:replace 开头请勿添加斜杠,避免部署运行的时候出现路径报错。(因为默认拼接的路径为spring.thymeleaf.prefix = classpath:/templates/

2.1.5 消息表达式

即通常的国际化属性:#{msg} 用于获取国际化语言翻译值。例如:

<title th:text="#{user.title}"></title>

2.1.6 其它表达式

在基础语法中,默认支持字符串连接、数学运算、布尔逻辑和三目运算等。例如:

<input name="name" th:value="${'I am '+(user.name!=null ? user.name:'NoBody')}"/>
常用的 th 标签
关键字功能介绍案例
th:id替换id<input th:id="'xxx' + ${collect.id}"/>
th:text文本替换<p th:text="${collect.description}">description</p>
th:utext支持html的文本替换<p th:utext="${htmlcontent}">conten</p>
th:object替换对象<div th:object="${session.user}">
th:value属性赋值<input th:value="${user.name}"/>
th:with变量赋值运算<div th:with="isEven=${prodStat.count}%2==0"></div>
th:style设置样式th:style="'display:' + @{(${sitrue} ? 'none' : 'inline-block')} + ''"
th:onclick点击事件th:onclick="'getCollect()'"
th:each属性赋值tr th:each="user,userStat:${users}">
th:if判断条件<a th:if="${userId == collect.userId}" >
th:unless和th:if判断相反<a th:href="@{/login}" th:unless=${session.user != null}>Login</a>
th:href链接地址<a th:href="@{/login}" th:unless=${session.user != null}>Login</a> />
th:switch多路选择 配合th:case 使用<div th:switch="${user.role}">
th:caseth:switch的一个分支<p th:case="'admin'">User is an administrator</p>
th:fragment布局标签,定义一个代码片段,方便其它地方引用<div th:fragment="alert">
th:include布局标签,替换内容到引入的文件<head th:include="layout :: htmlhead" th:with="title='xx'"></head> />
th:replace布局标签,替换整个标签到引入的文件<div th:replace="fragments/header :: title"></div>
th:selectedselected选择框 选中th:selected="(${xxx.id} == ${configObj.dd})"
th:src图片类地址引入<img class="img-responsive" alt="App Logo" th:src="@{/img/logo.png}" />
th:inline定义js脚本可以使用变量<script type="text/javascript" th:inline="javascript">
th:action表单提交的地址<form action="subscribe.html" th:action="@{/subscribe}">
th:remove删除某个属性<tr th:remove="all"> 1.all:删除包含标签和所有的孩子。
th:attr设置标签属性,多个属性可以用逗号分隔比如 th:attr="src=@{/image/aa.jpg},title=#{logo}",此标签不太优雅,一般用的比较少。

还有非常多的标签,这里只列出最常用的几个,由于一个标签内可以包含多个th:x属性,其生效的优先级顺序为:
include,each,if/unless/switch/case,with,attr/attrprepend/attrappend,value/href,src ,etc,text/utext,fragment,remove。

三、内置对象

3.1 七大内置对象

  • ${#ctx} 上下文对象,可用于获取其它内置对象。

  • ${#vars}: 上下文变量。

  • ${#locale}:上下文区域设置。

  • ${#request}: HttpServletRequest对象。

  • ${#response}: HttpServletResponse对象。

  • ${#session}: HttpSession对象。

  • ${#servletContext}: ServletContext对象。

3.2 常用的工具类:

  • #strings:字符串工具类

  • #lists:List 工具类

  • #arrays:数组工具类

  • #sets:Set 工具类

  • #maps:常用Map方法。

  • #objects:一般对象类,通常用来判断非空

  • #bools:常用的布尔方法。

  • #execInfo:获取页面模板的处理信息。

  • #messages:在变量表达式中获取外部消息的方法,与使用#{…}语法获取的方法相同。

  • #uris:转义部分URL / URI的方法。

  • #conversions:用于执行已配置的转换服务的方法。

  • #dates:时间操作和时间格式化等。

  • #calendars:用于更复杂时间的格式化。

  • #numbers:格式化数字对象的方法。

  • #aggregates:在数组或集合上创建聚合的方法。

  • #ids:处理可能重复的id属性的方法。

四、迭代循环

想要遍历List集合很简单,配合th:each 即可快速完成迭代。例如遍历用户列表:

<div th:each="user:${users}">
       id:<input id="id" name="id" th:value="${user.id}"/> <br>
       姓名:<input id="username" name="username" th:value="${user.username}"/> <br>
</div>

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j5b118Sk-1657013815625)(C:\Users\fm016\Desktop\新建文件夹\新建文件夹\7.png)]

在集合的迭代过程还可以获取状态变量,只需在变量后面指定状态变量名即可,状态变量可用于获取集合的下标/序号、总数、是否为单数/偶数行、是否为第一个/最后一个。例如:

<table>
    <tr>
        <td>下标</td>
        <td>序号</td>
        <td>id</td>
        <td>姓名</td>
        <td>年龄</td>
    </tr>

    <tr th:each="user,item:${users}">
        <td th:text="${item.index}">index</td>
        <td th:text="${item.count}">count</td>
        <td th:text="${user.id}">id</td>
        <td th:text="${user.username}">姓名</td>
        <td th:text="${user.age}">年龄</td>
    </tr>
</table>

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6tUawEDY-1657013815625)(C:\Users\fm016\Desktop\新建文件夹\新建文件夹\8.png)]

五、条件判断

条件判断通常用于动态页面的初始化,例如:

<div th:if="${users}">
    <div>哈哈哈,users存在</div>
</div>

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EGSIJnwE-1657013815626)(C:\Users\fm016\Desktop\新建文件夹\新建文件夹\9.png)]

如果想取反则使用unless 例如:

<div th:unless="${userList}">
    <div>不存在..</div>
</div>

六、日期格式化

使用默认的日期格式并不是我们预期的格式:Tue Jul 05 13:48:47 CST 2022

<h1 th:text="${user.creatTime}"></h1>

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gb5SgERN-1657013815626)(C:\Users\fm016\Desktop\新建文件夹\新建文件夹\10.png)]

此时可以通过时间工具类#dates来对日期进行格式化:2022-70-05 13:50:23

<h1 th:text="${#dates.format(user.createTime,'yyyy-MM-dd HH:mm:ss')}"></h1>

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ntau8SmW-1657013815627)(C:\Users\fm016\Desktop\新建文件夹\新建文件夹\11.png)]

七、内联写法

  • (1) 为什么要使用内联写法?
    答: 因为 JS 无法获取服务端返回的变量

  • (2) 如何使用内联表达式?
    答: 标准格式:[[${xx}]],可以读取服务端变量,也可以调用内置对象的方法。例如获取用户变量和应用路径:

<script>
    var users = `[[${userList}]]`;
    console.log("users :" + users)
</script>

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SEtCmMrL-1657013815627)(C:\Users\fm016\Desktop\新建文件夹\新建文件夹\12.png)]

  • (3) 标签引入的 JS 里面能使用内联表达式吗?

    答: 不能!内联表达式仅在页面生效,因为Thymeleaf只负责解析一级视图,不能识别外部标签 JS 里面的表达式。

九、Demo案例

创建 SpringBoot 项目,如图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fL7YKlhA-1657013815628)(C:\Users\fm016\Desktop\新建文件夹\新建文件夹\demo01.png)]

引入相关依赖

<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
    <!-- web相关依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- thymeleaf依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <!-- 热部署依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
    </dependency>
</dependencies>

然后在 application.yml 中配置

spring:
  thymeleaf:
    prefix: classpath:/templates/
    suffix: .html

编写 User 实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer id;
    private String username;
    private String password;
    private String address;
    private Date createTime;
}

编写 controller 层,返回用户信息

@Controller
public class UserController {

    @RequestMapping("/get")
    public String test01(Model model){
        ArrayList<User> userList = new ArrayList<>();

        userList.add(new User(1,"名字1","123456","成都",new Date()));
        userList.add(new User(2,"名字2","456789","grgk",new Date()));
        userList.add(new User(3,"名字3","789123","成都",new Date()));
        userList.add(new User(4,"名字4","987654","grgk",new Date()));

        model.addAttribute("userList",userList);
        return "user";
    }
}

编写前端 user.html 页面

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div th:each="user,userStat:${userList}">
        序号:<input type="text" th:value="${userStat.count}">
        账号:<input type="text" th:value="${user.username}">
        密码:<input type="text" th:value="${user.password}">
        时间:<input type="text" th:value="${user.createTime}">
        格式化后的时间:<input type="text" th:value="${#dates.format(user.createTime,'yyyy-MM-dd HH:mm:ss')}">
    </div>
</body>

<script>
    var users = `[[${userList}]]`;
    console.log("users :" + users)
</script>
</html>

然后访问 http://localhost:8080/get 运行结果如图所示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Iemweunh-1657013815628)(C:\Users\fm016\Desktop\新建文件夹\新建文件夹\demo02.png)]

u s e r . u s e r n a m e " > 密 码 : < i n p u t t y p e = " t e x t " t h : v a l u e = " {user.username}"> 密码:<input type="text" th:value=" user.username"><inputtype="text"th:value="{user.password}">
时间:
格式化后的时间:

```

然后访问 http://localhost:8080/get 运行结果如图所示

[外链图片转存中…(img-Iemweunh-1657013815628)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LpodE6Qw-1657013815628)(C:\Users\fm016\Desktop\新建文件夹\新建文件夹\demo22.png)]

  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值