后端程序员如何写出优雅的前端试图【Thymeleaf】

Thymeleaf

Thymeleaf 是一个现代服务器端 Java 模板引擎,适用于 Web 和独立环境。
【官网地址】:https://www.thymeleaf.org/

在这里插入图片描述


文章目录


一、初始Thymeleaf

1.1 Thymeleaf是什么?

Thymeleaf是一款现代化的Java模板引擎,适用于Web和独立开发。对前后端的协同工作非常友好相比于之前的传统的试图模板那引擎JSP而言。

可以处理HTML,CSS,JavaScript甚至纯文本。

1.2 特点

  • 直接在浏览器中打开并正确显示模板页面
  • 开箱即用的特性
  • 提供标准和Spring标准结合可以套用JSTL、OGNL

1.3 引用提示

要使用Thymeleaf的提示功能,可以在HTML的标签里添加如下命名空间

<html lang="en" xmlns:th="http://www.thymeleaf.org">

目前最新的Thymeleaf版本已经是3.0,在之前的老版本可能要使用如下的声明

<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">

声明:以上的方式针对于Idea用户,可以很好的提示,但是针对Eclipse用户需要安装Thymeleaf插件

如果需要 下载,可以去Spring的官网下载,或者自行百度搜索。

二、使用步骤

这里以SpringBoot来演示,下面为SpringBoot与 Thymeleaf的整合步骤

2.1 创建SpringBoot项目,导入Thymleaf依赖

Thymleaf的SpringBoot启动支持依赖🙉

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

当我们加上这个依赖就代表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=.html

2.2 快速上手

编写一个Controller

@Controller
public class TestController {

    @GetMapping("/test")
    public String hello(Model model){
        model.addAttribute("msg", "你好Thymeleaf");
        return "hello";
    }
}

编写页面hello.html解析

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<p>[[${msg}]]</p>
<p th:text="${msg}"></p>
</body>
</html>

访问localhost:8080/test
在这里插入图片描述

  • 这里的两种语法是Thymleaf的取值
  • 第一种[[${}]]适用于 追加文本
  • 第二种th:text=""适用于 替换文本

三、基础语法

3.1 表达式语法

  • 1.变量表达式
  • 2.选择或星号表达式
  • 3.文字国际化表达式
  • 4.URL表达式

1️⃣变量表达式🔥🔥

变量表达式即OGNL表达式或Spring EL表达式(在Spring术语中也叫model attributes)。

语法格式:${表达式}

如下所示:

${session.user.name}
<span th:text="${book.author.name}">  
<li th:each="book : ${books}">  
@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";
}
  • 获取普通数据类型
<p th:text="${MyName}"></p>
<p th:text="${MyAge}"></p>
  • 获取对象数据类型
<p>用户名:<span th:text="${student.name}"></span></p>
<p>用户id:<span th:text="${student.id}"></span></p>
<p>用户年龄:<span th:text="${student.age}"></span></p>
<p>用户邮箱:<span th:text="${student.email}"></span></p>
  • 引用数据类型
<!--引用数据类型-->
<p>用户学校名称:<span th:text="${student2.school.schoolName}"></span></p>
<p>用户学校地址:<span th:text="${student2.school.schoolAddress}"></span></p>

在这里插入图片描述

2️⃣选择(星号)表达式

选择表达式很像变量表达式,不过它们用一个预先选择的对象来代替上下文变量容器(map)来执行,如下:
*{customer.name}

被指定的object由th:object属性定义:

<div th:object="${book}">  
  ...  
  <span th:text="*{title}">...</span>  
  ...  
</div>  

3️⃣文字国际化表达式

文字国际化表达式允许我们从一个外部文件获取区域文字信息(.properties),用Key索引Value,还可以提供一组参数(可选).

#{main.title}  
#{message.entrycreated(${entryId})}  

可以在模板文件中找到这样的表达式代码:

<table>  
  ...  
  <th th:text="#{header.address.city}">...</th>  
  <th th:text="#{header.address.country}">...</th>  
  ...  
</table>  

创建一个资源文件用来提供国际化的模板提供

在这里插入图片描述

英文
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}

让我们看这些表达式:

<form th:action="@{/createOrder}"><a href="main.html" th:href="@{/main}">

{/} 是相对应用的根,即网页上下文

3.2 变量表达式和星号表达有什么区别吗?

如果不考虑上下文的情况下,两者没有区别;星号语法评估在选定对象上表达,而不是整个上下文
什么是选定对象?就是父标签的值,如下:

<div th:object="${session.user}">
  <p>Name: <span th:text="*{firstName}">Sebastian</span>.</p>
  <p>Surname: <span th:text="*{lastName}">Pepper</span>.</p>
  <p>Nationality: <span th:text="*{nationality}">Saturn</span>.</p>
</div>

这是完全等价于:

<div th:object="${session.user}">
  <p>Name: <span th:text="${session.user.firstName}">Sebastian</span>.
  </p><p>Surname: <span th:text="${session.user.lastName}">Pepper</span>.
  </p><p>Nationality: <span th:text="${session.user.nationality}">Saturn</span>.</p>
</div>

当然,美元符号和星号语法可以混合使用:

<div th:object="${session.user}">
  <p>Name: <span th:text="*{firstName}">Sebastian</span>.</p>
  <p>Surname: <span th:text="${session.user.lastName}">Pepper</span>.</p>
  <p>Nationality: <span th:text="*{nationality}">Saturn</span>.</p>
</div>

小例子:

public class HelloThymeleaf {
    public static void main(String[] args) {
        // 创建模板引擎
        TemplateEngine engine = new TemplateEngine();
        // 准备模板
        String input = "<input type='text' th:value='hello'/>";
        // Context 准备数据
        Context context = new Context();
        // 调用引擎 处理数据 和模板、
        String str = engine.process(input, context);
        System.out.println("结果数据:"+str);
    }
}

四、标准表达式

4.1 文本表达式

<h2>文本使用</h2>
<p th:text="学习文本表达式">文本处理</p>
<p th:text="'hello thymeleaf'">用空格的文本</p>
<p th:text="'学习'+${info}">连接字符串+</p>
<p th:text="'学习'+'java'">连接字符串+</p>
<p th:text="|您好 ${info}|">连接字符串+</p>
<p th:text="|${n1},${n2}|+'你好'">连接字符串+</p>
<p th:text="123">数字文本</p>
<p th:text="true">布尔文本</p>
<p th:text="${n1}"></p>
<p th:text="${n2}"></p>

在这里插入图片描述

注意:如果表达式中的字串有空格 空格需要配使用单引号 或者|xxx|,连接字串需要使用+号拼接

4.2 数字表达式

  • 字面量1+字面量2
  • 变 量 1 + {变量1}+ 1+{变量2}
<span>字面常量数字1+1:</span><p th:text="1+1"></p><hr>
<span>表达式的算数${n1}+${n2}:</span><p th:text="${n1}+${n2}"></p><hr>
<span>表达式结合的算术${n1}+1:</span><p th:text="${n1}+1"></p><hr>
<span>有字符串穿插的算术和运算1+1+'字符串'+2+4:</span><p th:text="1+1+'字符串'+2+4"></p>
<hr>
<span>括号提高优先级和运算1+1+'字符串'+(2+4):</span><p th:text="1+1+'字符串'+(3+4)"></p>
<hr>

在这里插入图片描述

4.3 布尔表达式

<p th:text="true">显示true</p>
<p th:if="${marriage}">已婚,能看到标签么</p>
<p th:if="${age} &lt; 20">您未成年</p>
<p th:if="${age} &gt; 20">您成年</p>
<p th:if="${marriage} and ${age} &gt; 18">符合法定结婚年龄 已婚</p>

**注意:如果需要使用逻辑表达式 需要使用 and or **

1️⃣表达式实体

  • gt 大于 >
  • lt 小于 <
  • ge 大于等于 >=
  • le 小于等于 <=
  • eq 等于 ==
  • not 非 !
  • neq 不等于 !=

4.4 NULL 和空字串

null字面量在页面中可以直接使用 也可以作为判断的依据是否为null 但数据为null式时,标签和内容不显示。同理”“空字串处理结果也一样。

创建一个NullController

@RequestMapping("/null")
public String doNull(Model model){
    model.addAttribute("null", null);
    model.addAttribute("emptys", "");
    return "null";
}

模板展示

<h2>空字符的使用</h2>
<p th:if="${null} == null">这是一个空</p>
<p th:if="${emptys} == ''">这是一个空字串</p>
<p th:text="${null}">null值</p>
<p th:text="''">空字串</p>
<p th:text="null">null值</p>

在这里插入图片描述

4.5 逻辑表达式

需要用到th:if的标签

  • and 与
  • or 或
  • not 非( !)
<p th:if="10>5">10大于5</p>
<p th:if="10 &gt; 5">10大于6</p>
<p th:if="10 < 12">10大于12</p>
<p th:if="10 &lt; 13">10大于13</p>
<p th:if="10 == 10">10等于10</p>
<p th:if="10 eq 10">10等于10</p>
<p th:if="not(false)">非假</p>
<p th:if="${isLogin}">登录成功</p>
<p th:if="!${isLogin}">未登录</p>

4.6 三元表达式

<p th:text="10>5?'10大于5':'10不大于5'"></p>
<p th:text="${age}>20?'age大于20':'age不大于20'"></p>
<p th:text="${age}!=null?'age是'+${age}:'age是null'"></p>
<p th:text="${age}!=null?(${age}>30?'age大于30':'age不够30'):'age是null'"></p>

三元表达式是可以嵌套使用的

五、设置属性值

属性作用
th:text计算其值表达式并将结果设置为标签的标签体
th:utextth: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:switch与Java中的switch语句等效 有条件的显示匹配的内容
th:case配合switch使用
th:with定义局部变量
th:inline禁用内联表达式,内联js、css

5.1 th:attr 设置任何属性值

th:attr 语法不优雅 可以使用th:value、th:action、th:href等替换

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head th:lang-xmllang="en">
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript">
        function fun1() {
            alert(111)
        }
    </script>
    <style>
        .large-font{
            font-size: 20px;
            color: red;
        }
    </style>
</head>
<body>
<form action="/hello.html" method="post" th:attr="action=${MyAction}">
    账号:<input type="text" name="username">
    密码:<input type="password" name="password">
    <input type="submit" th:attr="value=${mytext}">
    <input type="button" value="点我" th:attr="οnclick='fun1()'">
</form>

<a href="" th:class="large-font">超链接</a>

<image th:src="@{../static/image/1.jpg}" th:title="${mytext}" th:alt-title="我的最爱"></image>
</body>
</html>

5.2 布尔属性值设置

如果设置成了true则对应的属性值为显示相应的属性值 否则不显示

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

在这里插入图片描述

5.3 th:utext/th:text

@RequestMapping("/txt")
public String adTxt(Model model) {
    model.addAttribute("msg","学习开发语言<b>Java</b>");
    model.addAttribute("context","学习开发语言<b>MySQL</b>,<b>Vue</b>,<b>SpringBoot</b>");
    return "body";
}

html

<p th:text="${msg}"></p>
<p th:utext="${context}"></p>

在这里插入图片描述

5.4 th:each的使用🔥🔥

类似于jstl里面的c:forEach

特点:

  • 循环的对象包括自身的标签的全部内容
  • 如果循环体是一个空的或者不存在 则不循环
  • 可以遍历对象
    • 数组、集合,map,枚举

1️⃣语法格式:

<tr th:each=“成员遍历:${表达式}”>
	<td th:text="${成员}"></td>
</tr>
@RequestMapping("/each")
public String doEach(Model model) {
    List<Employee> 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️⃣ 遍历集合

<h3>遍历集合</h3>
<table border="1" cellspacing="0" cellpadding="0">
    <thead>
    <tr>
        <td>编号</td>
        <td>姓名</td>
        <td>年龄</td>
    </tr>
    </thead>
    <tr th:each="e : ${emp}">
        <td th:text="${e.id}"></td>
        <td th:text="${e.name}"></td>
        <td th:text="${e.age}"></td>
    </tr>
</table>

在这里插入图片描述

3️⃣遍历map

Map<String, Employee> map = 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集合是一个键不能为空,值可以为空的一个容器,键重复则覆盖

<h3>遍历Map</h3>
<table border="1" cellspacing="0" cellpadding="0">
    <thead>
    <tr>
        <td>编号</td>
        <td>姓名</td>
        <td>年龄</td>
    </tr>
    </thead>
    <tr th:each="e : ${maps}">
        <td  th:text=" ${e.key}"></td>
        <td th:text=" ${e.value.name}"></td>
        <td th:text=" ${e.value.age}"></td>
    </tr>
</table>

在这里插入图片描述

4️⃣遍历ListMap

@RequestMapping("/listMap")
    public String doListMap(Model model) {
        List<Map<String,Employee>> list = new ArrayList<>();

        Employee stu1 = new Employee(1, "占山", 21);
        Employee stu2 = new Employee(2, "李四", 51);
        Employee stu3 = new Employee(3, "王五", 45);
        Employee stu4 = new Employee(4, "赵六", 15);
        Employee stu5 = new Employee(5, "孙七", 34);
        Employee stu6 = new Employee(6, "刘能", 54);

        Map<String, Employee> map1 = new HashMap<>();
        Map<String, Employee> map2 = new HashMap<>();
        Map<String, Employee> map3 = new HashMap<>();

        map1.put("001", stu1);
        map1.put("002", stu2);
        map2.put("003", stu3);
        map2.put("004", stu4);
        map2.put("005", stu5);
        map3.put("006", stu6);

        list.add(map1);
        list.add(map2);
        list.add(map3);

        model.addAttribute("listMap", list);
        return "body";
    }
<h3>循环ListMap</h3>
<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>

在这里插入图片描述

5️⃣遍历数组Array

String[] arr = {"张飞","刘备","关羽"};
model.addAttribute("arr", arr);
<h3>遍历数组</h3>
<ul>
    <li th:each="name : ${arr}" th:text="${name}"></li>
</ul>

在这里插入图片描述

6️⃣循环下拉列表框的值

Map<String, String> cities = new HashMap<>();
cities.put("010", "天津");
cities.put("020", "湖南");
cities.put("030", "陕西");
cities.put("040", "上海");
model.addAttribute("cities", cities);
model.addAttribute("selected", true);
<h3>遍历下拉列表</h3>
<select name="" id="" >
    <option th:value="'--请选择城市--'" th:text="'--请选择城市--'" th:selected="${selected}"></option>
    <option th:each="city:${cities}" th:value="${city.key}" th:text="${city.value}"></option>
</select>

在这里插入图片描述

7️⃣循环状态值:🔥🔥

  • index属性:当前迭代的索引 从0开始
  • **count属性:**当前迭代的计数,从1开始
  • size属性:当前迭代变量中元素的总量
  • **current属性:**每次迭代的iter变量,即当前的遍历到的元素
  • even/odd属性:偶数还是奇数 布尔
    • true:偶数
    • false:基数
  • first:判断迭代的是否是第一个 也是一个布尔
  • last:判断迭代的是否是最后个 也是一个布尔

语法格式:

<tr th:each="循环变量,状态变量 : ${表达式}">
	<td th:text="状态变量名.状态值"></td>
</tr>
<h3>遍历集合</h3>
<table border="1" cellspacing="0" cellpadding="0">
    <thead>
    <tr>
        <td>编号</td>
        <td>姓名</td>
        <td>年龄</td>
        <td>循环状态循环的次数count</td>
        <td>循环状态循环的当前元素current</td>
        <td>循环状态当前迭代的计数size</td>
        <td>循环状态first</td>
        <td>循环状态last</td>
        <td>循环状态even</td>
        <td>循环状态odd</td>
    </tr>
    </thead>
    <tr th:each="e,loopStatus : ${emp}">
        <td th:text="${e.id}"></td>
        <td th:text="${e.name}"></td>
        <td th:text="${e.age}"></td>
        <td th:text="'总计循环数据共'+${loopStatus.count}+''"></td>
        <td th:text="'当前循环的数据'+${loopStatus.current}"></td>
        <td th:text="'总计循环数据共'+${loopStatus.size}+''"></td>
        <td th:text="${loopStatus.first}?'是第一条数据':'不是第一个数据'"></td>
        <td th:text="${loopStatus.last}?'是最后一条数据数据':'不是最后一条数据数据'"></td>
        <td th:text="${loopStatus.even}?'是偶数行':'是奇数行'"></td>
        <td th:text="${loopStatus.odd}?'是奇数行':'是偶数行'"></td>
    </tr>
</table>

在这里插入图片描述

5.5 th:if的使用

  • 如果变量值是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";
}
<h3>为真判断</h3>
<p th:if="true">判断是否true,true</p>
<p th:if="'true'">判断是否字串true,"true"</p>
<p th:if="99">判断是数字,99</p>
<p th:if="${old}">old</p>
<p th:if="${str0}">空字串</p>
<hr>
<h3>为假的判断</h3>
<p th:if="${marriage}">结婚了</p>
<p th:if="${Stroff}">off</p>
<p th:if="${Strno}">no</p>

在这里插入图片描述

5.6 unless的使用

不满足的条件显示,否则不显示,略

六、模板的使用

6.1 模板的语法

公用的重复的每个页面都是的时候,公共资源,可重复使用使用的资源可以定义为模板

模板的使用

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

1️⃣语法格式:

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

2️⃣引用模板

  • 把模板插入到当前位置**insert**
<div th:insert="模板所在的我呢见名称::模板名称">
    其他内容
</div>
  • 把模板替换到当前位置**replace**
<div th:replace="模板所在的我呢见名称::模板名称">   
    其他内容
</div>

3️⃣删除模板

  • 语法格式:
<div th:remove="删除范围值">
    
</div>

范围值:

  • all:删除的包含标签内的所有子项
  • body:不删除的包含标签内的所有子项
  • tag:删除包含标签,但不要删除其子项
  • all-but-first:删除第一个子项以外的其他子项
  • none:什么都不做,该值对于动态计数,null也可以作为社么也不做

6.2 模板的应用

1️⃣insert的应用

首先定义模板内容

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div th:fragment="header">
        <b>学习thymeleaf语法</b>
    </div>
    <div th:fragment="copy">
        &copy; 权限归魏永鹏所有 2020-2022
    </div>
    <div th:fragment="funtpl(one,two)">
        <p th:text="'hello'+${one}+','+${two} "></p>
    </div>
</body>
</html>

模板引用

<body>
    <p>使用Header名称的模板</p>
    <div th:insert="fragement/footer::header">
        插入header名称模板
    </div>
</body>

在这里插入图片描述

在插入 模板的时候还可以使用~这种语法来进行插入,效果与insert一致

语法如下:

<footr>
    <p>页脚</p>
    <div th:insert="fragement/footer::copy"></div>
    <div th:insert="~{fragement/footer::copy}"></div>
</footr>

在这里插入图片描述

函数模板的引用

<h3>参数模板的使用</h3>
<div th:insert="fragement/footer::funtpl(one='张三',two='李四')">
    参数模板的使用
</div>

在这里插入图片描述

当前页面引用模板

<div th:fragment="course">
	这是一个当前页面的模板
</div>

<h3>引用当前页面的模板</h3>
<div th:insert="::course"></div>
<div th:insert="~{::course}"></div>

在这里插入图片描述

id引用模板

<div id="fragment1">
    这是一个当前页面的模板2 使用id定义的模板
</div>

<h3>使用dom对象的id引用模板</h3>
<div th:insert="::#fragment1"></div>

2️⃣replace替换模板

在这里插入图片描述

3️⃣remove删除模板

<div th:fragment="dram1">
    这是一个自定义的模板
</div>

<p>引用模板dram1</p>
<div th:insert="::dram1"></div>
<hr>
<div th:remove="all">
    <span>1111</span>
    <ul>
        <li>1</li>
        <li>2</li>
    </ul>
</div>
<hr>
<div th:remove="body">
    <span>1111</span>
    <ul>
        <li>1</li>
        <li>2</li>
    </ul>
</div>
<hr>
<div th:remove="tag">
    <span>1111</span>
    <ul>
        <li>1</li>
        <li>2</li>
    </ul>
</div>
<hr>
<div th:remove="all-but-first">
    <span>1111</span>
    <ul>
        <li>1</li>
        <li>2</li>
    </ul>
</div>
<hr>
<div th:remove="none">
    <span>1111</span>
    <ul>
        <li>1</li>
        <li>2</li>
    </ul>
</div>

七、inline的使用🔥

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

7.1 内联语法

语法格式:

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

即[[]]或者[()]可以替换掉th:text或者th:utext

  • [[]]等效替换th:text
  • [()]等效替换th:utext

7.2 禁用内联

<p th:inline=“none”>

语法格式

<p  th:inline="none">原样输出的内容</p>

7.3 使用Javascript内联

语法格式

<script type="text/javascript" th:inline="javascript"></script>
@RequestMapping("/inline")
public String doInline(Model model) {
    List<Employee> 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

<script th:inline="javascript" type="text/javascript">
    var list = [[${list}]];
    var name = [[${name}]];
    console.log(name);

    for (var i = 0; i < list.length; i++) {
        console.log(list[i])
    }
</script>

如果要在js内敛中使用tymeleaf语法,则必须指定标签内为th:inline=‘javascript’

在这里插入图片描述

内联的优点:可以在标签内添加非模型数据

八、其他

8.1 局部变量

th:with定义的变量只能在该声明的标签内使用

@RequestMapping("/var")
public String doVar(Model model) {
    model.addAttribute("name","李四2");
    return "var";
}
<div th:with="name='张三'">
    <p>局部变量:[[${name}]]</p>
</div>
<p>全局设置的request域中的name值:[[${name}]]</p>

在这里插入图片描述

8.2 工具类的使用

1️⃣地址的解析#uris内置对象

<body th:with="myUrl='http://localhost:8080/myWeb/hello.jsp?username=张三'">
模板名称:<p th:text="${#execInfo.templateName}"></p>
模板模式:<p th:text="${#execInfo.templateMode}"></p>
<div th:with="espath=${#uris.escapePath(myUrl)}">
    编码的值:[[${espath}]]<br>
    解码的值:[[${#uris.unescapePath(espath)}]]<br>
</div>

在这里插入图片描述

2️⃣日期的解析#dates内置对象

<h3>格式化日期</h3>
<p>原始日期:[[${myDate}]]</p>
<p>解析后的日期:[[${#dates.format(myDate,'yyyy-MM-dd HH:mm:ss')}]]</p>

在这里插入图片描述

3️⃣数字的解析#unmbers内置对象

<h3>格式化数字</h3>
<p>原始数字:[[${price}]]</p>
<p>解析后的数字:[[${#numbers.formatInteger(price,0)}]]</p>
<p>解析后的数字:[[${#numbers.formatInteger(price,3)}]]</p>
<p>解析后的数字:[[${#numbers.formatDecimal(price,3,1)}]]</p>

参数解析:

  • 第一个参数是变量值
  • 第二个参数是整数位,不够前面补零
  • 第三个参数是小数位个数,同样遵循四舍五入的规律
字符串的解析#strings内置对象
<h3>格式化字符串</h3>
<p>原始字符串:[[${myName}]]</p>
<p>myName是否为空:[[${#strings.isEmpty(myName)}]]</p>
<p>解析后的字符串:[[${#strings.substring(myName,0,3)}]]</p>
<p>包含key的索引:[[${#strings.indexOf(myName,'key')}]]</p>
<p>包含kep的索引:[[${#strings.indexOf(myName,'kep')}]]</p>
<p>转大写:[[${#strings.toUpperCase(myName)}]]</p>

在这里插入图片描述

九、内置对象🔥🔥🔥

  • ${#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";
}
<p>request1:[[${myName}]]</p>
<p>request2:[[${myName2}]]</p>
<p>session:[[${session.sessionName}]]</p>
<p>context:[[${application.applicationName}]]</p>

在这里插入图片描述

优雅的写一个后台管理页面

静态资源:https://wwa.lanzoui.com/iGD3xl6i5ni
新建一个SpringBoot项目,引入核心的Thymeleaf依赖
将静态资源放入到static目录下,将所有的页面文件放入到templates目录下。

这里我只完成一个简单的登录功能

导入login.html,index.html,将index.html改名为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:/main.html";
        } else {
            model.addAttribute("msg", "账号密码错误");
            return "login";
        }

    }

    // 解决表单重复提交 重定向
    @GetMapping("/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}“

<form class="form-signin" th:action="@{/login}" method="post">
...
</form>

Thymeleaf还可以在JavaScript脚本中使用,在JS中使用就需要用到[[${}]]的语法来获取域中的值。

<script type="text/javascript">

    const msg = '[[${msg}]]';
    console.log(msg);

    if (msg == "账号密码错误") {
        alert(msg)
    }
</script>
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@WAT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值