这里写自定义目录标题
第一部分 认识Thymeleaf
什么是 Thymeleaf ?
Thymeleaf是一个现代服务器端Java模板引擎,适用于Web和独立环境,能够处理HTML,XML,JavaScript,CSS甚至纯文本。
Thymeleaf可以处理的模板?
- HTML
- XML
- Text
- JavaScript
- CSS
- RAW
两种标记模板模式 (HTML和XML)、三种文本模板模式 (Text,JavaScript,CSS ) 和一种无操作模板模式(RAW)
模板引擎的基本工作原理
1. 第一个Thymeleaf程序
- 创建一个非Web项目
导入依赖
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.15.RELEASE</version>
</dependency>
静态数据
HelloThymeleaf.java
public class HelloThymeleaf{
public static void main(String[] args){
//创建模板引擎
TemplateEngine engine = new TemplateEngine();
//准备模板
String input = "<input type='text' th:value='hellothymeleaf'/>";
//准备数据,使用Context
Context context = new Context();
//调用引擎,处理模板和数据
String out = engine.process(input,context);
System.out.println("result:"+out);
}
}
获取动态数据
HelloThymeleaf.java
public class HelloThymeleaf{
public static void main(String[] args){
//创建模板引擎
TemplateEngine engine = new TemplateEngine();
//准备模板
String inStr = "<input type='text' th:value='${name}'/>";
//准备数据,使用Context
Context context = new Context();
context.setVariable("name","lisi");
//调用引擎,处理模板和数据
String out = engine.process(inStr,context);
System.out.println("result:"+out);
}
}
2. 使用模板文件
在main目录下创建resources包,在resources中添加main.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input type="text" th:value="${name}" />
</body>
</html>
HelloThymeleaf.java
public class HelloThymeleaf{
public static void main(String[] args){
//创建模板引擎
TemplateEngine engine = new TemplateEngine();
//读取磁盘中的模板文件
ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
//设置引擎使用resovler
engine.setTemplateResolver(resolver);
//指定数据
Context context = new Context();
context.setVariable("name","lisi");
//处理模板
String out = engine.process("main.html",context);
System.out.println("result:"+out);
}
}
3. 设置模板前后缀
在resources目录下创建文件夹templates
创建index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input type="text" th:value="${name}" />
</body>
</html>
HelloThymeleaf.java
public class HelloThymeleaf{
public static void main(String[] args){
//创建模板引擎
TemplateEngine engine = new TemplateEngine();
//读取磁盘中的模板文件
ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
//设置前缀
resolver.setPrefix("templates/");
//设置后缀
resolver.setSuffix(".html");
//设置引擎使用resovler
engine.setTemplateResolver(resolver);
//指定数据
Context context = new Context();
context.setVariable("name","lisi");
//处理模板
String out = engine.process("index",context);
System.out.println("result:"+out);
}
}
4. SpringBoot中使用Thymeleaf
- 创建springboot项目,导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
- 编写application.properties
# 指定模板引擎主要处理的文件格式
spring.thymeleaf.mode=HTML
#指定模板文件所存放的位置 默认:classpath:/templates/
spring.thymeleaf.prefix=classpath:/templates/
# 指定模板文件的后缀名
spring.thymeleaf.suffix=.html
#不使用模板的缓存,每次都是用最新的模板数据
spring.thymeleaf.cache=false
- 编写controller文件
HelloController.java
@Controller
public class HelloController{
/*
参数:Model 可以存放数据,放到request作用域中
返回值: String:表示试图
*/
@RestMapping("/hello")
public String hello(Model model){
//添加数据
model.addAttribute("name","lisi");//指定模板视图
return "index";
}
}
- 不使用Model,可以使用HttpServletRequest,用request.attAttribute(“name”,”lisi”);
- 创建index.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="${name}"></p>
</body>
</html>
第二部分 表达式语法
1. 变量表达式
表达式形式:
${….}
- 用于获取后台传过来的值
例如:
<p th:text="${userName}"></p>
可以获取基本类型和引用类型
<p th:text="${name}"></p>
<p th:text="${student.id}"></p>
<!--student类的公共属性没有set和get方法,也可以访问到-->
<p th:text="${student.sex}"></p>
Student类有public或private属性有get方法,可以使用$获取信息
- 获取数据可以通过属性值也可以通过get方法
学校地址:<span th:text=“${student.my school.address}”></span>
<!—— 或 —->
学校地址:<span th:text=“${student.my school.getAddress()}”></span>
2. 选择变量表达式
表达式形式:
*{……}
3. 消息表达式(国际化)
表达式形式:
#{……}
- 用来获取资源文件中的数据
- 根据地区的不同来获取不同的语言表达内容
4. 链接网址表达式
表达式形式:
@{……}
- 用于替换网页中的src,href等的值
- 处理web应用中的url地址,可以是相对地址也可以是绝对地址
@{/}
:相对整个应用的根路径
例如:
<script type="text/javascript" th:href="@{/css/home.css}"></script>
<a th:href="@{http://www.baidu.com}"></a>
链接中传参数
使用的是get方式传参
/user/list?id=001
/user/list?id=001&name=张三
1)在@{……}
表达式末尾使用()
设置参数
<a th:href="@{/user/list(id=001)}"></a>
<!--多个参数-->
<a th:href="@{/user/list(id=001,name='张三')}"></a>
<!--动态传参-->
<a th:href="@{/user/list(id=001,name=${myname})}"></a>
5. 片段表达式
表达式形式:
~{……}
- 用于引用公共的目标片段
<div th:insert="~{footercopy}"></div>
第三部分 标准表达式
1. 文本
文本文字只是在单引号之间指定的字符串。它们可以包含任何字符,如果字符之中没有空格,可以不加单引号。使用“+
”连接文本,也可以使用“|
”
<p th:text="'hello thymeleaf'"></p>
<p th:text="'学习'+${info}"></p>
<p th:text="|欢迎使用 ${info}|"></p>
<p th:text="你好+|${n1},${s2}|"></p>
2. 数字
数字文字就是:数字,还包括算术运算:+,-,*,/和%,表达式中的值可以进行比较:<,>等等
html实体 | 符号 |
---|---|
& gt; | > |
lt | < |
ge | >= |
le | <= |
not | ! |
eq | == |
neq | != |
- 遇到字符串的拼接后面都是字符串了
- 如果出现括号
()
优先级高,先运算
<p th:text="6+6+'后面是字符了'+10+10"></p>
<!--输出为:12后面是字符了1010 -->
<p th:text="6+6+'后面不是字符了'+(10+10)"></p>
<!--输出为:12后面不是字符了20 -->
3. 布尔
<th:if="布尔值">,布尔值为true显示标签,反之不显示
<th:if="true|false">标签体</th:if>
<p th:if="${age} < 18">没有成年</p>
<p th:if="${married} and ${age} > 18">使用and</p>
4. null 和 “ ”
null
字面量,在页面直接使用,也可以判断数据是否为null
。当数据为null时,标签和内容不显示。“”
和null
处理结果一样。
model.addAttribute("name",null);
model.addAttribute("myname","");
<p th:text="null">这是null</p> //不显示
<p th:text="''">这是""</p> //不显示
<p th:text="${name}">后台值为null</p> //不显示
<p th:text="${myname}">后台值为""</p> //不显示
5. 比较/逻辑运算符
结合布尔使用
and(与) | or(或) | !(非) | not(非) |
---|
<p th:if="${age} < 18">没有成年</p>
<p th:if="${age} > 18">成年了</p>
6. 三元运算符
Thymeleaf中的三元运算与Java以及JavaScript中基本一致,如A>B?X:Y
,在XY中可以继续嵌套,只是thymeleaf中需要使用括号包含起来,否则报错。
A>B?X:Y
省略了Y,如果X>Y为false,整个表达式为null,标签不显示。
<p th:text="0>5 ? '10大于5': '10不大于5'">判断数字大小</p>
<p th:text="${age}!=null ? (${age}>30 ? '大于30': '不大于30'): 'age为null'">嵌套判断</p>
<p th:text="${islogin}?'没有登陆'">登录用户</p> //不显示
第四部分 设置属性值
属性 | 作用 |
---|---|
th:text | 计算其值表达式并将结果设置为标签的标签体 |
th:utext | th:text会对结果中的特殊字符转义,而th:utext不会 |
th:attr | 为标签中任意属性设值,可以一次设置多个属性 |
th:* | 为html指定的属性设值,一次设置一个;如th:value,th:type |
<input th:type="text" th:value="name"/>
1. 设置任意属性值 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="password" name="pwd"><br/>
<input type="submit" value="登录" th:attr="value=${mytext}">
</form>
- 设置多个属性
<input type="submit" value="登录" th:attr="value=${mytext},οnclick='fun1()'">
不运行模板时:
运行模板之后,将值进行替换:
2. 同时设置多个值
th:alt-title
:设置alt,title两个属性
th:lang-xmllang
:设置lang,xml:lang
<img th:src="@{/image/im1.jpg}" th:alt-title="我的图片" />
<img src="@{/image/im1.jpg}" alt="我的图片" title="我的图片" />
<head th:lang-xmllang="en"></head>
<head xml:lang="en" lang="en"></head>
3. boolean属性
HTML具有布尔属性的概念,例如 readonly,还有checkbox的“checked”,这个属性不赋值,默认改值为“true”。也可以使用属性名本身表示true,即checked=“checked”。
AttrController.java
model.addAttribute("selected",true);
model.addAttribute("unselected",false);
attr.html
<input type="checkbox" value="游泳" th:checked="${selected}">游泳<br/>
<input type="checkbox" value="骑行" th:checked="${unselected}">骑行<br/>
4. 设置标签体文本
th:text
:用来计算表达式并将结果设置标签体,会对计算结果中特殊字符进行转义。
th:utext
:用来计算表达式并将结果设置标签体,不会进行转义。
Controller.java
model.addAttribute("msg","学习的开发语言<b>java</b>等等");
model.addAttribute("xontent","全栈开发<b>vue</b>,<b>java</b>,<b>mysql</b>");
body.html
<p th:text="${msg}">text</p>
<p th:utext="${content}">text</p>
5. 循环th:each
th:each
处理循环,类似jstl中的<c:foreach>
特点:
- 循环的对象如果是null,不存在则不循环;
- 循环包含自身和标签内全部内容;
- 可以遍历的对象:
- 数组
- 任何实现
java.util.lterable
接口的对象 Enumeration
枚举Map
接口对象
语法格式:
<tr th:each="成员遍历:${表达式}">
<td th:text="${成员}">列</td>
</tr>
Controller.java
List<Student> students=new ArrayList<>();
list.add(new Student(1001,"ksda",18));
list.add(new Student(1002,"sdfas",18));
list.add(new Student(1003,"terw",18));
list.add(new Student(1004,"dfgs",18));
model.addAttribute("students",list);
html
<table>
<tr>
<th>id</th>
<th>姓名</th>
<th>年龄</th>
</tr>
<tr th:each="stu:${students}">
<td th:text="${stu.id}"></td>
<td th:text="${stu.name}"></td>
<td th:text="${stu.age}"></td>
</tr>
</table>
使用th:each
时,Thymeleaf提供了一种用于跟踪迭代状态的机制:状态变量。状态变量在每个th:each
属性中定义,并包含以下数据:
- index 属性:当前迭代索引,从0开始;
- count 属性:当前的迭代计数,从1开始;
- size 属性:迭代变量中元素的总量;
- current 属性:每次迭代的iter变量,即当前遍历到的元素;
- even/odd 布尔属性:当前的迭代是偶数还是奇数;
- first 布尔属性:当前的迭代是否是第一个迭代
- last 布尔属性:当前的迭代是否是最后一个迭代。
循环一个Map
Map<String,String> map=new HashMap<>();
map.put("id","学号");
map.put("name","学生姓名");
map.put("age","年龄");
map.put("classname","所在班级");
model.addAttribute("stumap",map);
html
<p th:each="m:${stumap}">
<span th:text="${m.key}"></span>
<span th:text="${m.value}"></span>
</p>
HashMap散列图、Hashtable散列表是按“有利于随机查找的散列(hash)的顺序”。并非按输入顺序。遍历时只能全部输出,而没有顺序。
循环list-map
List<Map<String,Student>> listmap=new ArrayList<>();
Map<String,Student> map=new HashMap<>();
map1.put("stu1",s1);
map1.put("stu2",s2);
map1.put("stu3",s3);
listmap.add(map1);
Map<String,Student> map=new HashMap<>();
//创建s4,s5,s6对象
map2.put("stu4",s4);
map2.put("stu5",s5);
map2.put("stu3",s6);
listmap.add(map2);
model.addAttribute("listmap",listmap;
双重循环获取属性及属性值
html
<ul th:each="lm:${listmap}">
<li th:each="entry:${lm}" th:key="${entry.key}"></li>
<li th:each="entry:${lm}" th:key="${entry.value}"></li>
</ul>
6. 判断th:if和th:unless
th:if
th:if
:当条件满足时,显示代码片段。条件常用boolean
表示,true满足,反之不满足。
thymeleaf中,true不是唯一满足条件。
1)如果表达式结果为布尔值,则为true或者false;
2)如果表达式的值为null,th:if将判定此表达式为false;
3)如果值是数字,为0时,判断为false;不为0时,判定为true;
4)如果值是String,值为“false”,“off”,“no”时,判定为false,否则为true,字符串为空时,也判断为true。
5)如果值不是布尔值,数字,字符或字符串的其他对象,只要不为null,则判断为true。
th:unless
th:unless
是不满足条件显示代码片段,类似Java中if的else部分。
7. 模板使用
模板就是公用资源,可以多次重复使用的内容。经常把页眉,页脚,菜单做成模板,在各个其他页面也使用。
模板的使用,先定义再使用。可以在当前页面定义模板,也可在其他页面中定义模板。
1)定义模板语法:
<div th:fragment="模板名称">
模板内容
</div>
2)引用模板(常用insert
和replace
)
- 把模板插入到当前位置(在div里面将模板插入)
<div th:insert="模板所在文件名称::模板名称">
其他内容
</div>
- 把模板替换到当前标签内容(替换div为模板)
<div th:replace="模板所在文件名称::模板名称">
其他内容
</div>
- 模板内容(不包含标签)添加到当前标签
<div th:include="模板所在文件名称::模板名称">
其他内容
</div>
使用id引用模板
<p id="tplid">
这是模板
</p>
<div th:insert="::#tplid">
</div>
3)模板引用语法
- 模板所在文件名称::模板名称
- ~{模板所在文件名称::模板名称}
- 当前页面:::模板名称
或
~{::course}
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:fragment="menu">
<b>首页|开发语言|开发工具|咨询</b>
</div>
使用模板
@GetMapping("/tpl")
public String doTemplate(Model model){
model.addAttribute("tplname","menu");
return "frag/main";
}
<p>使用model中的数据表示模板名称</p>
<div th:insert="frag/footer::${tplname}"></div>
<br/>
8. th:inline 使用
灵活,使用更方便。
需要将thymeleaf表达式写到标签体中,而不是标签内,可以使用
1)内联语法
[[]]
或[()]
内联表达式,任何在th:text
或th:utext
属性中使用的表达式都可以出现在[[]]
或[()]
中使用。
[[]]
:等价于th:text
[()]
:等价于th:utext
2)禁用内联
内容
;里面的内容原样输出。3)使用JavaScript内联
<script th:inline="javascript">
var msg = [[${message}]];
if(msg){
window.onload=function(){
alert(msg);
}
}
</script>
9. th:with 局部变量
th:with="变量名1=值1,变量名2=值2"
,定义的变量只在当前标签内有效。
@GetMapping("/var")
public String doVar(Model model){
model.addAttribute("age",20);
return "var";
}
var.html
<!--单个变量-->
<div th:with="name='zhangsan'">
<p th:text="${name}"/>
</div>
<!--多个变量-->
<div th:with="id=1001,name='zhangsan',myage=${age}">
<p th:text="${id}"/>
<p th:text="${name}"/>
<p th:text="${myage}"/>
</div>
10. 工具类对象
1)#{execInfo}
:模板信息
${#execInfo.templateName}
:模板名称${#execInfo.templateMode}
:模板的处理方式
2)#uris
:处理url/uri编码解码
${#uris.escapePath(uri)}
:编码${#uris.escapePath(uri,encoding)}
:指定编码转码${#uris.UnescapePath(uri)}
:解码${#uris.unescapePath(uri,encoding)}
:指定编码解码
3)#dates
:java.util.Date对象的实用程序方法,可以操作数组,set,list。
常用方法:
${#dates.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(datesSet, 'dd/MMM/yyyy HH:mm')}
4)#numbers
:数字对象的实用程序方法
${#numbers.formatInteger(num,size)}
:num表示被格式的数字,size表示整数位最少保留几位。
5)#strings
String工具类,就是字符串工具类
${#strings.toUpperCase(name)}
:大写${#strings.toLowerCase(name)}
:小写${#strings.arrayJoin(namesArray,',')}
:连接,合并${#strings.arraySplit(namesStr,',')}
:分隔${#strings.indexof(name,frag)}
:查找- ${#strings.indexof(name,‘san’)}
${#strings.substring(name,3,5)}
:取子串${#strings.contains(name,'ez')}
:是否有字串${#strings.isEmpty(name)}
:判断是否为空
6)#ids
,#aggregates
,#maps
,#sets
,#lists
,#arrays
,#bools
,#objects
等等工具类
@GetMapping("/tools")
public String doVar(Model model){
model.addAttribute("mydate",new Date());
model.addAttribute("price",89.35);
model.addAttribute("myname","zhangsan");
return "tools";
}
tools.html
11. 内部对象
#request,就是javax.servlet.http.HttpServletRequest
contextPath:[[${#request.getContextPath()}]]
获取请求参数:[[${#request.getParameter('name')}]]
getAttribute:[[${#request.getAttribute('attrName')}]]
#session,直接访问与当前请求关联的javax.servlet.http.HttpSession对象
getAttribute:[[${#session.getAttribute('sessionAttr')}]]
getId:[[${#session.getId()}]]
#servletContext:直接访问与当前请求关联的javax.servlet.ServletContext对象
-
[[${#servletContext.getAttribute('contextAttr')}]]
-
获取服务器信息:
[[${#servletContext.getServerInfo()}]]
快捷对象
thymeleaf在web环境中,有一系列的快捷方式用于访问请求参数、会话属性等应用属性。
param:用于检索请求参数。 p a r a m . f o o 是一个使用 f o o 请求参数的值 S t r i n g [ ] ,所以 {param.foo}是一个使用foo请求参数的值String[],所以 param.foo是一个使用foo请求参数的值String[],所以{param.foo[0]}将会通常用于获取第一个值。
例:http://localhost:8080/myweb/hello.jsp?foo=lisi&foo=zhangsan&name=dsfd&userid=1001
foo是一个数组。
param获取参数:[[${param.foo[0]}]]
param获取参数:[[${param.foo[1]}]]
参数数量:[[${param.size()}]]
是否有指定参数:[[${param.containsKey('name')}]]
获取参数值:[[${param.userid}]]
session:用于获取session属性。与param同理,只是作用域不同。
作用域的值:[[${session.sessionAttr}]]
session中key的数量:[[${session.size()}]]
application:用于获取应用程序或servlet上下文属性。与param同理。
获取ServletContext作用域的值:[[${application.contextAttr}]]
application中key的数量:[[${application.size()}]]
使用springboot会向全局作用域中添加容器信息,实际上比自己定义的key的数量还多。