Thymeleaf 是一个现代服务器端 Java 模板引擎,适用于 Web 和独立环境。
【官网地址】:https://www.thymeleaf.org/
文章目录
- Thymeleaf
- 一、初始Thymeleaf
- 1.1 Thymeleaf是什么?
- 1.2 特点
- 1.3 引用提示
- 二、使用步骤
- 2.1 创建SpringBoot项目,导入Thymleaf依赖
- 2.2 快速上手
- 三、基础语法
- 3.1 表达式语法
- :one:变量表达式:fire::fire:
- 获取普通数据类型
- 获取对象数据类型
- 引用数据类型
- :two:选择(星号)表达式
- :three:文字国际化表达式
- :four:URL表达式:fire::fire:
- 3.2 变量表达式和星号表达有什么区别吗?
- 四、标准表达式
- 4.1 文本表达式
- 4.2 数字表达式
- 4.3 布尔表达式
- :one:表达式实体
- 4.4 NULL 和空字串
- 4.5 逻辑表达式
- 4.6 三元表达式
- 五、设置属性值
- 5.1 th:attr 设置任何属性值
- 5.2 布尔属性值设置
- 5.3 th:utext/th:text
- 5.4 th:each的使用:fire::fire:
- :one:语法格式:
- :two: 遍历集合
- :three:遍历map
- :four:遍历ListMap
- :five:遍历数组Array
- :six:循环下拉列表框的值
- :seven:循环状态值::fire::fire:
- 5.5 th:if的使用
- 5.6 unless的使用
- 六、模板的使用
- 6.1 模板的语法
- :one:语法格式:
- :two:引用模板
- :three:删除模板
- 6.2 模板的应用
- :one:insert的应用
- :two:replace替换模板
- :three:remove删除模板
- 七、inline的使用:fire:
- 7.1 内联语法
- 7.2 禁用内联
- 7.3 使用Javascript内联
- 八、其他
- 8.1 局部变量
- 8.2 工具类的使用
- :one:地址的解析`#uris`内置对象
- :two:日期的解析`#dates`内置对象
- :three:数字的解析`#unmbers`内置对象
- 字符串的解析`#strings`内置对象
- 九、内置对象:fire::fire::fire:
- 优雅的写一个后台管理页面
一、初始Thymeleaf 1.1 Thymeleaf是什么?
Thymeleaf是一款现代化的Java模板引擎,适用于Web和独立开发。对前后端的协同工作非常友好相比于之前的传统的试图模板那引擎JSP而言。
可以处理HTML,CSS,JavaScript甚至纯文本。
1.2 特点- 直接在浏览器中打开并正确显示模板页面
- 开箱即用的特性
- 提供标准和Spring标准结合可以套用JSTL、OGNL
要使用Thymeleaf的提示功能,可以在HTML的标签里添加如下命名空间
目前最新的Thymeleaf版本已经是3.0,在之前的老版本可能要使用如下的声明
声明:以上的方式针对于Idea用户,可以很好的提示,但是针对Eclipse用户需要安装Thymeleaf插件
如果需要 下载,可以去Spring的官网下载,或者自行百度搜索。
二、使用步骤2.1 创建SpringBoot项目,导入Thymleaf依赖这里以SpringBoot来演示,下面为SpringBoot与 Thymeleaf的整合步骤
Thymleaf的SpringBoot启动支持依赖
org.springframework.boot spring-boot-starter-thymeleaf
当我们加上这个依赖就代表SpringBoot已经帮我们将Thymeleaf自动配置了
【源码】ThymeleafAutoConfiguration类
@EnableConfigurationProperties({ThymeleafProperties.class})
@ConditionalOnClass({TemplateMode.class, SpringTemplateEngine.class})
@AutoConfigureAfter({WebMvcAutoConfiguration.class, WebFluxAutoConfiguration.class})
public class ThymeleafAutoConfiguration {
}
自动配好的策略:
- 1、所有的Thymeleaf的配置值都在:ThymeleafProperties类
- 2、配好了ThymeleafTemplateEngine
- 3、配好了ThymeleafViewResolver
- 4、我们只需要写页面即可
如果说想要自己定义Thymeleaf的一些配置,也可以在yml或者properties里自己定义:下面给出一个properties的样例:
# 应用名称 spring.application.name=boot-05-web-admin # 应用服务 WEB 访问端口 server.port=8080 # THYMELEAF (ThymeleafAutoConfiguration) # 开启模板缓存(默认值: true ) spring.thymeleaf.cache=true # 检查模板是否存在,然后再呈现 spring.thymeleaf.check-template=true # 检查模板位置是否正确(默认值 :true ) spring.thymeleaf.check-template-location=true #Content-Type 的值(默认值: text/html ) spring.thymeleaf.content-type=text/html # 开启 MVC Thymeleaf 视图解析(默认值: true ) spring.thymeleaf.enabled=true # 模板编码 spring.thymeleaf.encoding=UTF-8 # 要被排除在解析之外的视图名称列表,⽤逗号分隔 spring.thymeleaf.excluded-view-names= # 要运⽤于模板之上的模板模式。另⻅ StandardTemplate-ModeHandlers( 默认值: HTML5) spring.thymeleaf.mode=HTML5 # 在构建 URL 时添加到视图名称前的前缀(默认值: classpath:/templates/ ) spring.thymeleaf.prefix=classpath:/templates/ # 在构建 URL 时添加到视图名称后的后缀(默认值: .html ) spring.thymeleaf.suffix=.html2.2 快速上手
编写一个Controller
@Controller
public class TestController {
@GetMapping("/test")
public String hello(Model model){
model.addAttribute("msg", "你好Thymeleaf");
return "hello";
}
}
编写页面hello.html解析
Title
[[${msg}]]
访问localhost:8080/test
- 这里的两种语法是Thymleaf的取值
- 第一种[[${}]]适用于 追加文本
- 第二种th:text=""适用于 替换文本
- 1.变量表达式
- 2.选择或星号表达式
- 3.文字国际化表达式
- 4.URL表达式
变量表达式即OGNL表达式或Spring EL表达式(在Spring术语中也叫model attributes)。
语法格式:${表达式}
如下所示:
${session.user.name}
@RequestMapping("/expression-var")
public String expression(Model model) {
// 普通数据类型
model.addAttribute("MyName", "张三");
model.addAttribute("MyAge", 20);
// 对象数据类型
Student student = new Student();
student.setId(1001);
student.setName("yaml");
student.setEmail("yaml@qq.com");
student.setAge(21);
model.addAttribute("student", student);
// 引用数据类型
Schools school = new Schools();
school.setSchoolName("到北小学");
school.setSchoolAddress("陕西咸阳");
student.setSchool(school);
model.addAttribute("student2",student);
return "var1";
}
- 获取普通数据类型
- 获取对象数据类型
用户名:
用户id:
用户年龄:
用户邮箱:
- 引用数据类型
2️⃣选择(星号)表达式用户学校名称:
用户学校地址:
选择表达式很像变量表达式,不过它们用一个预先选择的对象来代替上下文变量容器(map)来执行,如下:
*{customer.name}
被指定的object由th:object属性定义:
3️⃣文字国际化表达式... ... ...
文字国际化表达式允许我们从一个外部文件获取区域文字信息(.properties),用Key索引Value,还可以提供一组参数(可选).
#{main.title}
#{message.entrycreated(${entryId})}
可以在模板文件中找到这样的表达式代码:
| ... | ... | ...
|---|
创建一个资源文件用来提供国际化的模板提供
英文 login=login 中文 login=登录
编写一个配置文件
public class MyLocalResolver implements LocaleResolver {
@Override
public Locale resolveLocale(HttpServletRequest request) {
String lang = request.getParameter("lang");
Locale locale = request.getLocale();
if (!StringUtils.isEmpty(lang)) {
String[] data = lang.split("_");
locale = new Locale(data[0], data[1]);
}
return locale;
}
@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
}
}
@Configuration
public class MyConfig implements WebMvcConfigurer {
@Bean
public LocaleResolver localeResolver(){
return new MyLocalResolver();
}
}
@RequestMapping("/i18n")
public String i18n(Model model){
return "login";
}
4️⃣URL表达式
URL表达式指的是把一个有用的上下文或回话信息添加到URL,这个过程经常被叫做URL重写。
@{/order/list}
URL还可以设置参数:
@{/order/details(id=${orderId})}
相对路径:
@{../documents/report}
让我们看这些表达式:
超链接如果设置成了true则对应的属性值为显示相应的属性值 否则不显示
model.addAttribute("selected", true);
model.addAttribute("unselect", false);
游泳5.3 th:utext/th:text
骑行
@RequestMapping("/txt")
public String adTxt(Model model) {
model.addAttribute("msg","学习开发语言Java");
model.addAttribute("context","学习开发语言MySQL,Vue,SpringBoot");
return "body";
}
html
5.4 th:each的使用
类似于jstl里面的c:forEach
特点:
- 循环的对象包括自身的标签的全部内容
- 如果循环体是一个空的或者不存在 则不循环
- 可以遍历对象
- 数组、集合,map,枚举
@RequestMapping("/each")
public String doEach(Model model) {
List list = new ArrayList<>();
list.add(new Employee(1, "占山", 21));
list.add(new Employee(2, "李四", 51));
list.add(new Employee(3, "王五", 45));
list.add(new Employee(4, "赵六", 15));
list.add(new Employee(5, "孙七", 34));
list.add(new Employee(6, "刘能", 54));
list.add(new Employee(7, "谢广坤", 23));
model.addAttribute("emp",list);
return "body";
}
2️⃣ 遍历集合
遍历集合
| 编号 | 姓名 | 年龄 |
Mapmap = new HashMap<>(); map.put("1", new Employee(1, "占山", 21)); map.put("2", new Employee(2, "李四", 51)); map.put("3", new Employee(3, "王五", 45)); map.put("4", new Employee(4, "赵六", 15)); map.put("5", new Employee(5, "孙七", 34)); map.put("6", new Employee(6, "刘能", 54)); model.addAttribute("maps", map);
注意:map集合是一个键不能为空,值可以为空的一个容器,键重复则覆盖
遍历Map
| 编号 | 姓名 | 年龄 |
@RequestMapping("/listMap")
public String doListMap(Model model) {
List
循环ListMap
String[] arr = {"张飞","刘备","关羽"};
model.addAttribute("arr", arr);
遍历数组
Mapcities = new HashMap<>(); cities.put("010", "天津"); cities.put("020", "湖南"); cities.put("030", "陕西"); cities.put("040", "上海"); model.addAttribute("cities", cities); model.addAttribute("selected", true);
遍历下拉列表7️⃣循环状态值:
- index属性:当前迭代的索引 从0开始
- **count属性:**当前迭代的计数,从1开始
- size属性:当前迭代变量中元素的总量
- **current属性:**每次迭代的iter变量,即当前的遍历到的元素
- even/odd属性:偶数还是奇数 布尔
- true:偶数
- false:基数
- first:判断迭代的是否是第一个 也是一个布尔
- last:判断迭代的是否是最后个 也是一个布尔
语法格式:
遍历集合
| 编号 | 姓名 | 年龄 | 循环状态循环的次数count | 循环状态循环的当前元素current | 循环状态当前迭代的计数size | 循环状态first | 循环状态last | 循环状态even | 循环状态odd |
- 如果变量值是String类型,其具体的值是false,off,no时,则表示时false,否则为true,字符串为空时,也判断为true
- 如果只是一个布尔类型,数字,字符或者字符串的其他对象,只要不为null,则判断为true
- 当条件为true时,则显示,否则不显示
演示:
@RequestMapping("/iftest")
public String doIf(Model model) {
// 真的
model.addAttribute("old", "true");
model.addAttribute("login", "login");
model.addAttribute("bool", true);
model.addAttribute("num1", 12);
model.addAttribute("num2", -2);
model.addAttribute("old", 0);
model.addAttribute("str0", "");
model.addAttribute("object", new Student());
// 假的
model.addAttribute("marriage", "false");
model.addAttribute("falseflag", false);
model.addAttribute("Stroff", "off");
model.addAttribute("Strno", "no");
return "if";
}
为真判断5.6 unless的使用判断是否true,true
判断是否字串true,"true"
判断是数字,99
old
空字串
为假的判断结婚了
off
no
不满足的条件显示,否则不显示,略
六、模板的使用 6.1 模板的语法公用的重复的每个页面都是的时候,公共资源,可重复使用使用的资源可以定义为模板
模板的使用
- 先定义,在使用,可以定义在当前页面的模板,也可以定义在其他页面
2️⃣引用模板模板内容
- 把模板插入到当前位置**insert**
其他内容
- 把模板替换到当前位置**replace**
3️⃣删除模板其他内容
- 语法格式:
范围值:
- all:删除的包含标签内的所有子项
- body:不删除的包含标签内的所有子项
- tag:删除包含标签,但不要删除其子项
- all-but-first:删除第一个子项以外的其他子项
- none:什么都不做,该值对于动态计数,null也可以作为社么也不做
首先定义模板内容
Title
学习thymeleaf语法
© 权限归魏永鹏所有 2020-2022
模板引用
使用Header名称的模板
插入header名称模板
在插入 模板的时候还可以使用~这种语法来进行插入,效果与insert一致
语法如下:
页脚
函数模板的引用
参数模板的使用参数模板的使用
当前页面引用模板
这是一个当前页面的模板引用当前页面的模板
id引用模板
这是一个当前页面的模板2 使用id定义的模板
使用dom对象的id引用模板
2️⃣replace替换模板
3️⃣remove删除模板
七、inline的使用这是一个自定义的模板引用模板dram1
1111
- 1
- 2
1111
- 1
- 2
1111
- 1
- 2
1111
- 1
- 2
1111
- 1
- 2
需要在thymeleaf表达式写到标签体中,而不是写道标签内,可以使用内联语法
7.1 内联语法语法格式:
[[…]]或者[(…)]内敛表达式在任何th:text或者th:utext属性中使用的表达式都可以出现在[[]],[()]中使用
7.2 禁用内联即[[]]或者[()]可以替换掉th:text或者th:utext
- [[]]等效替换th:text
- [()]等效替换th:utext
【语法格式】
7.3 使用Javascript内联原样输出的内容
【语法格式】
@RequestMapping("/inline")
public String doInline(Model model) {
List list = new ArrayList<>();
list.add(new Employee(1, "张三", 21));
list.add(new Employee(2, "李四", 25));
list.add(new Employee(3, "王五", 34));
model.addAttribute("name", "刘备");
model.addAttribute("list", list);
return "inline";
}
html页面使用js
如果要在js内敛中使用tymeleaf语法,则必须指定标签内为th:inline=‘javascript’
内联的优点:可以在标签内添加非模型数据
八、其他 8.1 局部变量th:with定义的变量只能在该声明的标签内使用
@RequestMapping("/var")
public String doVar(Model model) {
model.addAttribute("name","李四2");
return "var";
}
8.2 工具类的使用 1️⃣地址的解析#uris内置对象局部变量:[[${name}]]
全局设置的request域中的name值:[[${name}]]
模板名称: 模板模式:2️⃣日期的解析#dates内置对象编码的值:[[${espath}]]
解码的值:[[${#uris.unescapePath(espath)}]]
格式化日期3️⃣数字的解析#unmbers内置对象原始日期:[[${myDate}]]
解析后的日期:[[${#dates.format(myDate,'yyyy-MM-dd HH:mm:ss')}]]
格式化数字原始数字:[[${price}]]
解析后的数字:[[${#numbers.formatInteger(price,0)}]]
解析后的数字:[[${#numbers.formatInteger(price,3)}]]
解析后的数字:[[${#numbers.formatDecimal(price,3,1)}]]
参数解析:
- 第一个参数是变量值
- 第二个参数是整数位,不够前面补零
- 第三个参数是小数位个数,同样遵循四舍五入的规律
格式化字符串九、内置对象原始字符串:[[${myName}]]
myName是否为空:[[${#strings.isEmpty(myName)}]]
解析后的字符串:[[${#strings.substring(myName,0,3)}]]
包含key的索引:[[${#strings.indexOf(myName,'key')}]]
包含kep的索引:[[${#strings.indexOf(myName,'kep')}]]
转大写:[[${#strings.toUpperCase(myName)}]]
- ${#ctx.request} request域对象
- ${#ctx.response} response域对象
- ${#ctx.session} session域对象
- ${#ctx.serveltContext} application域对象
@RequestMapping("/scope")
public String doScope(Model model, HttpServletRequest request) {
model.addAttribute("myName","keppys");
request.setAttribute("myName2", "jakson");
request.getSession().setAttribute("sessionName", "jerry");
request.getSession().getServletContext().setAttribute("applicationName", "offer");
return "scope";
}
优雅的写一个后台管理页面request1:[[${myName}]]
request2:[[${myName2}]]
session:[[${session.sessionName}]]
context:[[${application.applicationName}]]
静态资源:https://wwa.lanzoui.com/iGD3xl6i5ni
新建一个SpringBoot项目,引入核心的Thymeleaf依赖
将静态资源放入到static目录下,将所有的页面文件放入到templates目录下。
这里我只完成一个简单的登录功能
导入login.html,index.html,将index.html改名为https://blog.csdn.net/mmklo/article/details/main.html
编写控制层,使用Thymeleaf语法在html页面实现登陆的跳转
// 去登陆页
@GetMapping(value = {"/", "/login"})
public String loginPage() {
return "login";
}
// 登录请求
@PostMapping(value = "/login")
public String main(User user, HttpSession session, Model model) {
// 这块可以写一些数据库账号密码的逻辑操作
// ...
// 如果密码账号无误,ok登录 把登录信息放到Session作用域中
// 这里只做非空判断
if (!StringUtils.isEmpty(user.getUsername()) && user.getPassword().equalsIgnoreCase("123456")) {
// 保存登陆成功的用户
session.setAttribute("loginUser", user);
return "redirect:/https://blog.csdn.net/mmklo/article/details/main.html";
} else {
model.addAttribute("msg", "账号密码错误");
return "login";
}
}
// 解决表单重复提交 重定向
@GetMapping("/https://blog.csdn.net/mmklo/article/details/main.html")
public String mainPage(HttpSession session, Model model) {
// 判断登录
Object loginUser = session.getAttribute("loginUser");
if (loginUser != null) {
return "main";
} else {
model.addAttribute("msg", "您未登录,请先登录在访问");
return "login";
}
}
Login.html中表单的action属性替换为Thymeleaf语法th:action=”@{/login}“
Thymeleaf还可以在JavaScript脚本中使用,在JS中使用就需要用到[[${}]]的语法来获取域中的值。



