thymeleaf

模板:准备呈现给用户的视图页面

数据:提供数据有多种方式

request.setAttribute();
model.addtribute();

模板引擎:处理模板和数据的程序。获取模板,吧模板中的特定符号,替换为数据,生成输出结果文件

jsp也是一种模板

thymeleaf:服务器端的模板引擎

一、什么是Thymeleaf

​ Thymeleaf是一个表现层的模板引擎,一般被使用在Web环境中,它可以处理HTML,XML,JS等文档,简单来说,它可以将JSP作为Java Web应用的表现层,有能力展示与处理数据。Thymeleaf可以让表现层的界面节点与程序逻辑被共享,这样的设计,可以让界面设计人员、业务人员与技术人员都参与到项目开发中。

​ 这样,同一个模板文件,既可以使用浏览器直接打开,也可以放到服务器中用来显示数据,并且样式之间基本不会存在差异,因此界面设计人员与程序设计人员可以使用同一个模板文件,来查看静态与动态数据的效果。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XwsGNbMT-1642483354230)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210815144232819.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PSe6yR4C-1642483354231)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210815144535680.png)]

可以从类路径中来读取我们所需的模板文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AMVfmCIY-1642483354231)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210815145638172.png)]

例:设置模板的前缀,后缀

前缀为模板文件相对于类路径下的一个目录名称,后缀来指定模板文件的扩展名

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ENl8D8jI-1642483354232)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210815150611028.png)]

thymeleaf-springboot环境搭建

编写application.properties

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nuUSywRt-1642483354233)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210815151438668.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A5Ufszow-1642483354234)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210815152701232.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qVf1Hgew-1642483354234)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210817163458727.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1too21bo-1642483354235)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210817163744567.png)]

表达式语法

1、表达式分类

序号 表达式 描述 例子
1 ${…} 变量表达式,可用于获取后台传过来的值 <p th:text="${username}">hahha</p>
2 *{…} 选择变量表达式
3 #{…} 消息表达式
4 @{…} 链接网址表达式,用于替换网页中的src,href等的值 th:href="@{/css.home.css}"
5 ~{…} 片段表达式,可以用于引用公共的目标片段 <div th:insert="~{footer :: copy}"></div>

2、变量表达式${…}

获取基本类型变量

获取对象类型

新建数据类Student

新建Controller

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-owUOjAAk-1642483354236)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210817172600585.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mmMls3D4-1642483354237)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210817172634941.png)]

Student的属性是public或者属性是private且有public类型getXXX的方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8Qhq5Lwe-1642483354238)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210817173758254.png)]

选择表达式*{…}

链接表达式@{…}

@{…}表达式用于处理web应用中的url地址,可以是相对地址,也可以是绝对地址

@{/}是相对应用根路径,其他都是相对当前路径

@{/}斜杠开头表示相对整个应用根目录,"/"表示“/应用上下文路径”

th:href是一个修饰符属性,将表达式结果设置为标签href属性的值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tCHwDHR0-1642483354239)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210817175906661.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oTPq1fyA-1642483354240)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210817175842451.png)]

链接中传参数

1)在@{…}表达式末尾使用“()"设置参数

@{/user/list(id=1001,name=zs)}

2)多个参数时,使用","隔开

3)参数值可以使用表达式动态取值

@{/user/list(id=1001,name=${name})}

消息表达式(国际化)

#{…}

实现

1、在resources目录下创建国际化的资源文件

目录 i18n

messages.properties

login=login|登录

messages_zh_CN.properties

login=登录

message_en_US.properties

login=Login

2、创建LocaleResolver实现类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UaFoIkBi-1642483354240)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210818014455568.png)]

3、创建mvc配置类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ICVK0bV8-1642483354241)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210818014523727.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4bPHW7eQ-1642483354242)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210819103131459.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0TztK4da-1642483354243)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210819103157633.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jN3irGuo-1642483354244)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210819103225852.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l8jSLRuT-1642483354245)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210819103245598.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fJKR4ReF-1642483354245)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210819103316080.png)]

标准表达式

文本

​ 文本文字只是在单引号之间指定的字符串,它们可以包含任何字符,如果字符之中没有空格,可以不加单引号。使用”+“连接文本,也可以使用”|“连接文本

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cXmajDPl-1642483354247)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210819111601207.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GSf3Zj0J-1642483354248)(C:\Users\pumpkin\AppData\Roaming\Typora\typora-user-images\image-20210819111623288.png)]

数字

数字文本就是:数字,算术运算也可用:+,-,*,/和%,表达式中的值可以进行比较>,<,>=,<=符号,以及==和!=可以被用来检查是否相等,一些符合需要使用实体gt(>),lt(<),ge(>=),le(<=),not(!),eq(==),neq(!=)

1、创建NumberController

2、创建num.html

p th:text="6+6+'后面是字符了'+10+20">

6+6是加法运算,遇到’'后面是字符串连接,不能在数字运算了

p th:text="6+6 + '这回不一样' + (10+20)"

括号的优先级高,6+6是加法10+20后再连接字符串

布尔

布尔是true,false

and(与),or(或),not(非),!(非)

<th:if="布尔值">,布尔值为true显示标签,反之不显示

<th:if="true|false">标签值</th:if>

null和“”

null字面量,在页面直接使用,也可以判断数据是否为null,当数据为null,标签和内容不显示,“”字符串和null处理结果一样

比较/逻辑运算符

表达式中的值可以与>,<,>=,<=,==,!=符号进行比较,一个更简单的代替方案是使用这些运算符的文本别名&gt;(>),&lt;(<),&ge;(>=),&le;(<=),eq(==),neq(!=)

逻辑运算符:and(与)、or(或)、!(非)、not(非)

<p th:if="not(false)">not(false)</p>
<p th:if="!false">!false非假为true</p>

三元运算符

thymeleaf中的三元运算与java以及javascript中基本一致,如A>B?X:Y,在X、Y中可以继续嵌套,只是Thymeleaf中需要使用括号括起来,否则报错

<p th:text="${age}!=null?(${age}&gt;30?'大于30':'不够30'):'age是null'">嵌套的三元</p>

设置属性值

属性 作用
th:text 计算其值表达式并将结果设置为标签的标签体
th:utext th:text会对结果中的特殊字符转义,th:utext不会转义
th:attr 为标签中的任意属性设置,可以一次设置多个属性
th:* 为html指定的属性设值,一次设置一个
th:alt-title 同时为alt与title属性赋值
th:lang-xmllang 同时为lang、xml:lang属性赋值
th:fragment 定义模板片段
th:insert 将被引用的模板片段插入到自己的标签体中
th:replace 将引用的模板片段替换掉自己
th:include 类似于th:insert,而不是插入片段,它只插入此片段内容
th:remove 删除模板中的某些代码片段
th:each 迭代数据,如数组、List、Map等
th:if 条件为true时,显示模板片段,否则不显示
th:unless 条件为false时,显示模板片段,否则不显示
th:case 配合th:switch使用
th:with 定义局部变量
th:inline 禁用内联表达式,内联js,内联css

设置任何属性值 th:attr

经过模板处理之后,可以给任意属性赋值

th:attr提供了更改标签属性值的能力,th:attr使用比较少,因为他的使用比较难,语法不优雅,对于标签的特定属性,请使用th:value,th:action,th:href,th:class,th:src,th:onclick等等

<form action="/hello.html" method="post" th:attr="action=${myaction}">
	账号:<input type="text" name="username"><br/>
	密码:<input type="text" name="pwd"><br/>
	<input type="submit" value="登录" th:attr="value=${mytext}">
</form>
<head>
    <script type="text/javascript">
    	function fun1(){
            alert("button click");
		}
    </script>
</head>

<form action="/hello.html" method="post" th:attr="action=${myaction}">
	账号:<input type="text" name="username"><br/>
	密码:<input type="text" name="pwd"><br/>
	<input type="button" value="登录" th:attr="οnclick='fun1()',value=${mytext}">
</form>

这样更直接方便

<form th:action="@{/user/listuser}" method="get">
    username:<input type="text" value="" name="username"><br/>
    password:<input type="text" value="" name="pwd"><br/>
    <input type="submit" th:value="${mytext}">
</form>

同时设置多个值

<img th:src="@{/image/im1.jpg}" th:alt-title="我的图片" />
<head th:lang-xmllang="en">
</head>

alt 属性是一个必需的属性,它规定在图像无法显示时的替代文本。

boolean属性

HTML具有布尔属性的概念,例如readonly,还有checkbox的“checked”,这个属性不赋值,没有值的属性意味着该值为“true”

也可以使用属性名本身表示true,即checked=“checked”

model.addAttribute("selected",true);
model.addAttribute("unselected",false);
<input type="checkbox" value="游泳" th:checked="${selected}">游泳
<input type="checkbox" value="骑行" th:checked="${unselected}">骑行

设置标签体文本

th:text

th:utext

循环th:each

th:each处理循环,类似jstl中的<c:foreach>

特点:

①循环的对象如果是null,不存在则不循环

②循环包含自身和标签内全部内容

③可以遍历的对象:

数组

任何实现java.util.Iterable接口的对象

Enumeration枚举

实现Map接口对象

语法格式:

<tr th:each="成员遍历:${表达式}">
	<td th:text="${成员}">列</td>
</tr>

使用th:each时,Thymeleaf提供了一种用于跟踪迭代状态的机制:状态变量。状态变量在每个th:each属性中定义,并包含以下数据:

①index属性:当前迭代索引,从0开始

②count属性:当前的迭代计数,从1开始

③size属性:迭代变量中的元素的总量

④current属性:每次迭代的iter变量,即当前遍历到的元素

⑤even/odd布尔属性:当前的迭代是偶数还是奇数

⑦first布尔属性:当前的迭代是否是第一个迭代

⑧last布尔属性:当前的迭代是否是最后一个迭代

<tbody>
    <tr th:each="mystu:${students}">
        <td th:text="${mystu.id}"></td>
        <td th:text="${mystu.name}"></td>
        <td th:text="${mystu.age}"></td>
    </tr>
</tbody>
<p th:each="m:${stumap}">
    <span th:text="${m.key}"></span>
    <span th:text="${m.value}"></span>
</p>
<ul th:each="lm:${listmap}">
    <li th:each="entry:${lm}"th:text="${entry.key}"></li>
    <li th:each="entry:${lm}"th:text="${entry.value}"></li>
</ul>
<select>
    <option value="0">请选择</option>
    <option th:each="cm:${citys}" th:value="${cm.key}" th:text="${cm.value}" th:selected="${cm.value} eq ${choice}">城市</option>
</select>
<tr th:each="stu,loopStatus:${stulist}">
	<td th:text="${loopStatus.count}+'/'+${loopStatus.size}"></td>
    <td th:text="${stu.id}">学号</td>
    <td th:text="${stu.name}">姓名</td>
    <td th:text="${stu.age}">年龄</td>
    <td th:text="${stu.className}">班级</td>
    <td th:text="${loopStatus.odd}?'奇数行':'偶数行'"></td>
    <td th:text="${loopStatus.odd}"></td>
</tr>

判断th:if和th:unless

th:if当条件满足时,显示代码片段,条件常用boolean表示,true满足,反之不满足

thymeleaf中,true不是唯一满足条件

1)如果表达式结果为布尔值,则为true或者false

2)如果表达式的值为null,th:if将判断此表达式为false

3)如果值是数字,为0时,判断为false;不为零时,判定为true

4)如果值是String,值为”false“、”off”、“no”时,判定为false,否则判断为true,字符串为空时,也判断为true

5)如果值不是布尔值、数字、字符或字符串的其它对象,只要不为null,则判断为true

th:unless是不满足条件显示代码片段,类似java中if的else部分

模板使用

模板就是公共资源,可以多次重复使用的内容,经常把页眉、页脚、菜单做成模板,在各个其它页面使用

模板使用,先定义再使用,可以在当前页面定义模板,也可在其他页面中定义模板

1)定义模板语法

<div th:fragment="模板名称">
    模板内容
</div>

2)引用模板

①把模板插入到当前位置

<div insert="模板所在文件名称::模板名称">
    其他内容
</div>

②用模板替换当前标签内容

<div replace="模板所在文件名称::模板名称">
    其他内容
</div>

③模板内容添加到当前标签

<div include="模板所在文件名称::模板名称">
    其他内容
</div>

3)模板引用语法

①:模板所在文件名称::模板名称

②:~{模板所在文件名称::模板名称}

4)模板作为函数形式使用

<div th:fragment="funtpl(one,two)">
    <p th:text="'hello' + ${one} + '-' + ${two}"></p>
</div>

th:insert,th:replace使用funtpl模板,可以传入值

<div th:replace="frag/footer::funtpl(one='张三',two='李四')">
    我是参数模板
</div>

5)删除模板

th:remove=“删除范围值”

①all:删除包含标签及其所有子项

②body:不删除包含标签,但删除所有的子项

③tag:删除包含标签,但不要删除其子项

④all-but-first:删除第一个子项以外的其他所有子项

⑤none:什么也不做,该值对于动态计算有用,null也会被视为none

<div th:insert="::course">
    使用当前页面定义的模板
</div>
<div th:insert="~{::course}">
    使用当前页面中的定义的模板
</div>

#表示id值

<p id="tplId">
    这是我们使用的id定义的模板
</p>
<p>
    使用dom对象的id来引用模板
</p>
<div th:insert="::#tplId">
</div>

th:inline使用

需要在thymeleaf表达式写到标签体中,而不是标签内,可以使用内联语法

1)[[…]]或[(…)]内联表达式,任何在th:text或th:utext属性中使用的表达式都可以出现在[[]]或[()]中使用

[[…]]等价于th:text;[(…)]等价于th:utext

2)禁用内联<p th:inline=“none”>原样输出的内容</p>

3)使用javascript内联

<script type=“text/javascript” th:inline=“javascript”>

<script type="text/javascript" th:inline="javascript">
	var jsname=[[${name}]];
    console.log("jsname:" + jsname)
    var stulist=[[${students}]];
    for(var i=0;i<stulist.length;i++){
        console.log("i="+i+","+stulist[i].name);
    }
</script>
<body>
    <p th:text="${name}">
        我是常用写法
    </p>
    <p>
        内联语法:[[${name}]]
    </p>
</body>

th:with局部变量

th:with=“变量名1=值1,变量名2=值2”,定义的变量只在当前标签内有效

工具类对象

1)#{execInfo}:模板信息

${#execInfo.templateName}模板名称

${#execInfo.templateMode}模板的处理模式

2)#uis

处理url/uri编码解码

${#uris.escapePath(uri)}编码

${#uris.escapePath(uri,encoding)}指定编码转码

${#uris.unescapePath(uri)}解码

${#uris.unescapePath(uri,encoding)}指定编码解码

3)#dates:java.util.Date对象的实用程序方法。可以操作数组、set、list

常用方法

${#date.format(date,'dd/MMM/yyyy HH:mm')}

${#dates.arrayFormat(datesArray,'dd/MMM/yyyy HH:mm')}

${#dates.listFormat(datesList,'dd/MMM/yyyy HH:mm')}

${#dates.setFormat(dateSet,'dd/MMM/yyyy HH:mm')}

4)#numbers:数字对象的实用程序方法

${#numbers.formatInteger(num,size)}num表示被格式的数字,size表示整数位最少保留几位

5)#string String工具类,就是字符串工具类

${#strings.toUpperCase(name)}大写

${#strings.toLowerCase(name)}小写

${#strings.arrayJoin(namesArray,',')}连接,合并

${#strings.arraySplit(nameStr,',')}分隔

${#strings.indexOf(name,frag)}查找

${#strings.substring(name,3,5)}取子串

${#strings.contains(name,'ez')}是否有子串

${#strings.isEmpty(name)}空判断

内置对象

#request,就是javax.servlet.http.HttpServletRequest

#session,就是javax.servlet.http.HttpSession

#servletContext,直接访问与当前请求关联的javax.servlet.ServletContext对象

thymeleaf在web环境中,有一系列的快捷方式用于访问请求参数、会话属性等应用属性

param,request,session访问它们而无需#

param:用于检索请求参数

快捷对象param,request,application使用,不需要#

param参数集合

获取数组第0个参数值:[[${param.foo[0]}]]

获取数组第1个参数值:[[${param.foo[1]}]]

请求中参数数量:[[${param.size()}]]

请求中userid参数值:[[${param.userid}]]

判断请求是否有指定参数:[[${param.containsKey(‘name’)}]]

session:用于获取session属性。与param同理,只是作用域不同而已

获取session指定的key的value:[[${session.sessionAttr}]]

session中key的数量:[[${session.size()}]]

application:用于获取应用程序或servlet上下文属性,与param同理

获取ServletContext中的数量:[[${application.contextAttr}]]

获取ServletContext中key的数量:[[${application.size()}]]

vletContext对象

thymeleaf在web环境中,有一系列的快捷方式用于访问请求参数、会话属性等应用属性

param,request,session访问它们而无需#

param:用于检索请求参数

快捷对象param,request,application使用,不需要#

param参数集合

获取数组第0个参数值:[[${param.foo[0]}]]

获取数组第1个参数值:[[${param.foo[1]}]]

请求中参数数量:[[${param.size()}]]

请求中userid参数值:[[${param.userid}]]

判断请求是否有指定参数:[[${param.containsKey(‘name’)}]]

session:用于获取session属性。与param同理,只是作用域不同而已

获取session指定的key的value:[[${session.sessionAttr}]]

session中key的数量:[[${session.size()}]]

application:用于获取应用程序或servlet上下文属性,与param同理

获取ServletContext中的数量:[[${application.contextAttr}]]

获取ServletContext中key的数量:[[${application.size()}]]

上一篇:SpringBoot2,2021最新阿里Java面试流程


下一篇:Thymeleaf教程(10分钟入门)