SpringBoot学习篇3[静态资源、Thymeleaf模板引擎]

本文详细介绍了SpringBoot中处理静态资源的路径、自定义欢迎页和图标,以及如何使用Thymeleaf模板引擎,包括其配置、标准表达式语法、常用属性等,展示了Thymeleaf在处理变量、链接、选择表达式等方面的应用。
摘要由CSDN通过智能技术生成

开始之前

在开始之前,先创建项目spring-boot-web
在这里插入图片描述
添加Spring Web和Thymeleaf依赖
在这里插入图片描述
勾选那两项是为了在Maven中引入以下两个依赖:
在这里插入图片描述
创建好后的项目目录如下(框起来的部分可以删除):
在这里插入图片描述

一 静态内容

1.1 静态资源的查找路径

默认情况下,Spring Boot从类路径中名为/static、/public、/resources或/META-INF/resources的目录下查找静态内容。
在resources下创建这三个目录:static、public、resources,并在static目录下创建hello.html文件,文件写入以下内容:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>静态资源文件</title>
</head>
<body>
    <h2>这是static目录下的静态资源文件</h2>
</body>
</html>

启动/重启项目,访问一下http://localhost:8080/hello.html
在这里插入图片描述
将hello.html文件移动到public或resources目录后,重启项目,再访问一下:
在这里插入图片描述
在这里插入图片描述

1.2 修改资源文件映射路径

默认情况下,资源映射到/**(即在浏览器中通过http://localhost:8080/xxx即可访问到xxx资源文件),也可以使用spring.mvc.static-path-pattern属性对其进行调整。例如,将所有资源重新映射到/resources/**可以通过以下方式实现:

spring.mvc.static-path-pattern=/resources/**

重启项目,再访问一下,发现已经访问不到了:
在这里插入图片描述
在url上加上/resources/后再试一下‘
在这里插入图片描述

1.2 欢迎页面

Spring Boot支持静态和模板欢迎页面。它首先在静态资源文件的查找目录中查找index.html文件,如果未找到,则寻找index模板文件。如果找到任何一个,它将自动作为web应用的欢迎界面(即在浏览器中通过http://localhost:8080直接访问到的页面)。
创建index.html文件,并将其放入任一静态资源文件路径下,写入以下内容:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
    <h1>这是首页</h1>
</body>
</html>

重启项目,在浏览器访问一下(注意:如果修改了资源文件映射路径的话,将访问不到
在这里插入图片描述

1.3 自定义图标

Spring Boot支持自定义图标,在这里提供两种方式:
方法一:
Spring Boot将在静态资源文件目录查找favicon.ico文件,如果找到了,将以此作为web应用的图标(需要清除浏览器缓存才能看得到)。
在这里插入图片描述
方法二:
1.配置spring.mvc.favicon.enabled属性为false
2.在index.html中添加以下代码

<link rel="icon" type="image/x-icon" href="/images/favicon.ico">

方法二有点投机取巧的意思。在访问首页时,浏览器缓存了web应用的图标,而后只要不清除缓存,浏览器显示的就是首页设定的图标。

二 模板引擎

2.1 Spring Boot支持的模板引擎

Spring MVC支持提供动态HTML内容。Spring MVC支持各种模板技术,包括Thymeleaf,FreeMarker和JSP。
SpringBoot对以下模板引擎做了自动配置的支持:

  • FreeMarker
  • Groovy
  • Thymeleaf
  • Mustache

SpringBoot官方不推荐使用JSP。将JSP与嵌入式Servlet一起使用时,将存在一些局限,具体可参考官方文档

在默认情况下,使用这些模板引擎之一时,Spring Boot将从resources/templates目录下提取模板引擎。

在这里插入图片描述

2.2 使用Thymeleaf模板引擎

2.2.1 引入Thymeleaf

  • 确保pom.xml文件中有添加依赖

    <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    
  • 在使用Thymeleaf的html页面上声明名称空间

    <html xmlns:th="http://www.thymeleaf.org">
    
  • Thymeleaf不支持像访问静态资源那样直接被访问。为了看到效果,编写Controller调用我们的Thymeleaf测试文件。

    package com.yky.springboot.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    
    @Controller
    public class ThymeleafTestController
    {
        @GetMapping(value = "/thymeleaf")
        public String callMyThymeleaf()
        {
            return "ThymeleafTest";
        }
    }
    
    

ThymeleafTest放到了templates/ThymeleafTest.html路径下。

2.3 Thymeleaf标准表达式语法

2.3.1 message表达式

格式: #{…}

message表达式用于从资源文件中读取内容,并显示在页面上。message表达式的主要用途是用于显示国际化信息,这部分知识将会在本篇文章后面讲解。

<!DOCTYPE html>
<html lang="en">
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>标题</title>
</head>
<body>
    <p th:text="#{home.welcome}"></p>
</body>
</html>

在配置文件中有配置home.welcome的值:
在这里插入图片描述
效果:
在这里插入图片描述
message表达式还支持传入参数:

<p th:text="#{home.welcome('爱学习的少年')}"></p>

配置文件内容:

home.welcome=你好,{0},欢迎

在message表达式传的第一个参数将替代{0},传递的第二个参数将替代{1},以此类推。。。。

2.3.2 变量表达式

格式:${}
变量表达式主要有以下功能:

  • 获取变量值
    如:${today}
  • 获取对象属性,调用对象方法,支持OGNL表达式
    如:${employee.name}
  • 使用内置对象
    如:${#locale.country}

[1]获取变量:

@Controller
public class ThymeleafTestController
{
    @GetMapping(value = "/thymeleaf")
    public String callMyThymeleaf(Map<String,Object> map)
    {
        map.put("today",new Date());
        return "ThymeleafTest";
    }
}
<div th:text="${today}"></div>

效果:
在这里插入图片描述
[2]获取对象属性,调用对象方法
新创建Employee对象如下:

package com.yky.springboot.entity;

public class Employee
{
    private String name;
    private Integer id;
    private Double salary;

	getter,setter方法
	toString方法
}

ThymeleafTestController代码改写如下:

@GetMapping(value = "/thymeleaf")
    public String callMyThymeleaf(Map<String,Object> map)
    {
        map.put("today",new Date());

        Employee employee = new Employee();
        employee.setName("yky");
        employee.setId(10);
        employee.setSalary(15000D);
        
        map.put("employee",employee);
        return "ThymeleafTest";
    }

html添加以下代码:

	<table border="1px">
        <tr>
            <td>姓名</td>
            <td>工号</td>
            <td>薪资</td>
        </tr>
        <tr>
            <td th:text="${employee.name}"></td>
            <td th:text="${employee.getId()}"></td>
            <td th:text="${employee.salary}"></td>
        </tr>
    </table>

效果如下:
在这里插入图片描述
[3] 使用内置对象或工具类
上面的日期显示的有点让人看不懂,不如用内置dates对象转换一下:

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

效果:
在这里插入图片描述
其支持的内部对象有:

  • #ctx : the context object.
  • #vars: the context variables.
  • #locale : the context locale.
  • #request : (only in Web Contexts) the HttpServletRequest object.
  • #response : (only in Web Contexts) the HttpServletResponse object.
  • #session : (only in Web Contexts) the HttpSession object.
  • #servletContext : (only in Web Contexts) the ServletContext object.

其支持的工具类有:

  • #execInfo : information about the template being processed.
  • #messages : methods for obtaining externalized messages inside variables expressions, in the same way as they would be obtained using #{…} syntax.
  • #uris : methods for escaping parts of URLs/URIs
  • #conversions : methods for executing the configured conversion service (if any).
  • #dates : methods for java.util.Date objects: formatting, component extraction, etc.
  • #calendars : analogous to #dates , but for java.util.Calendar objects.
  • #numbers : methods for formatting numeric objects.
  • #strings : methods for String objects: contains, startsWith, prepending/appending, etc.
  • #objects : methods for objects in general.
  • #bools : methods for boolean evaluation.
  • #arrays : methods for arrays.
  • #lists : methods for lists.
  • #sets : methods for sets.
  • #maps : methods for maps.
  • #aggregates : methods for creating aggregates on arrays or collections.
  • #ids : methods for dealing with id attributes that might be repeated (for example, as a result of an iteration).

上述工具类的用法参照官方文档

2.3.3 选择表达式

格式:*{…}
选择表达式的和变量表达式类似,在功能上是一样的。下面先来看看它的用法:

	<table border="1px">
        <tr>
            <td>姓名</td>
            <td>工号</td>
            <td>薪资</td>
        </tr>
        <tr>
            <td th:text="${employee.name}"></td>
            <td th:text="${employee.getId()}"></td>
            <td th:text="${employee.salary}"></td>
        </tr>

        <tr th:object="${employee}">
            <td th:text="*{name}"></td>
            <td th:text="*{getId()}"></td>
            <td th:text="*{salary}"></td>
        </tr>
    </table>

可以很明显看到选择表达式和变量表达式的区别:当选择表达式配合th:object一起使用时,可以省掉对象名前缀。

2.3.4 链接

格式:@{…}
当有用到uri时推荐使用此表达式。
比如提交表单时的action、a标签的href属性等,常常配合th:action、th:href、th:src等属性使用。

<a th:href="@{/}">回到首页</a>

还支持字符串拼接和传递参数(替代了?xxx=xx的形式):

<a th:href="@{${url}(orderId=${o.id})}">view</a>
<a th:href="@{'/details/'+${user.login}(orderId=${o.id})}">view</a>

2.3.5 片段表达式

2.3.6 字面量

[1] 文本文字
直接使用单引号
‘working web application’

<p>
Now you are looking at a <span th:text="'working web application'">template file</span>.
</p>

[2] 数字
2013,2013+2,3.1415,5.0

<p>The year is <span th:text="2013">1492</span>.</p>
<p>In two years, it will be <span th:text="2013 + 2">1494</span>.</p>

[3] 布尔值
true、false

 <div th:if="${user.isAdmin()} == false"> ...

<div th:if="${user.isAdmin() == false}"> ...

[4] null值
null

<div th:if="${variable.something} == null"> ...

[5] 文本标记
数字、布尔值和null实际上是文字标记的一种特殊情况。
这些标记允许在标准表达式中进行一些简化。它们的工作原理与文本文字(’…’)完全相同,但它们只允许字母(A-Z和A-Z)、数字(0-9)、括号([和])、点(.)、连字符(-)和下划线(_)。没有空格,没有逗号,等等。
标记文本不需要单引号,这使得代码看上去更加简练:

<p>
Now you are looking at a <span th:text="working_web_application">template file</span>.
</p>

2.3.7 文本操作

[1] 追加文本
直接使用+号拼接

 <span th:text="'The name of the user is ' + ${user.name}">

[2] 文本替换

 <span th:text="|Welcome to our application, ${user.name}!|">

等同于

 <span th:text="'Welcome to our application, ' + ${user.name} + '!'">

文本替换还可以与其他类型表达式组合使用

<span th:text="${onevar} + ' ' + |${twovar}, ${threevar}|">

2.3.8 算数运算

算数运算支持+ , - , * , / 和 % .

<p th:text="20 * 5"></p>

2.3.9 比较运算

支持:gt ( > ), lt ( < ), ge ( >= ), le (<=), not (!).Also eq (==), neq/ne (!=).

<p th:if="20 > 10" th:text="显示该内容"/>
<p th:if="20 == 10" th:text="不显示该内容"/>

2.3.10 布尔运算

支持:and、or、not(!)

<p th:if="not true" th:text="不显示该内容"/>

2.3.11 三目运算

[1] if-then
格式:(if) ? (value)

<p th:text="${employee.id} <= 10 ? '领导'"></p>

[2] if-then-else
格式:(if) ? (value1) : (value2)

<p th:text="${employee.salary} > 10000 ? '高薪资':'低薪资'"></p>

[3] default
格式:(if) ? : (defaultValue)
如果前者不为空,取前者。否则,取后者。

<p th:text="${employee.name} ?: '姓名为空,未知'"></p>

2.4 Thymeleaf常用属性

官方文档列出的Thymeleaf属性如下:

属性说明
th:insert 、th:replace片段包含
th:each迭代
th:if 、 th:unless 、 th:switch 、 th:case条件判断
th:object、th:with声明变量
th:attr 、 th:attrprepend 、 th:attrappend修改任意属性, prepend前面追加, append后面追加
th:value 、 th:href 、 th:src 、 …修改HTML原生属性
th:text、th:utext标签体内容修改 ,th:utext会解析HTML在界面中显示相应的效果,th:text不会
th:fragment片段声明
th:remove片段移除

在2.2.2表达式语法那一节其实就已经使用了Thymeleaf的某些属性,下面再针对常用属性进行说明一下。

2.4.1 th:text、th:utext显示标签体内容

显示标签体内容用th:text或th:utext属性,下面看一下两者的用法。
在Controller中添加下面一行代码:

map.put("msg","<h1>上午好</h1>");

在HTML获取msg:

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

看一下效果:
在这里插入图片描述
可以看到两者都显示出来了,两者的区别是th:text只会将文本原样显示,th:utext有解析html的功能。

2.4.2 行内表达式

前面刚说了在标签体上显示内容,Thymeleaf还支持在非标签体上显示内容。
格式:[[…]]
还是上面那个例子:

	<p th:text="${msg}"></p>
	<p th:utext="${msg}"></p>
    [[${msg}]]
    <p> Hello,[[${employee.name}]] </p>

显示效果:
在这里插入图片描述

2.4.3 th:each迭代

为了演示迭代,在Controller中加入以下代码:

		Employee employee1 = new Employee();
        employee1.setName("name1");
        employee1.setId(1);
        employee1.setSalary(14000D);

        Employee employee2 = new Employee();
        employee2.setName("name2");
        employee2.setId(2);
        employee2.setSalary(14500D);

        Employee employee3 = new Employee();
        employee3.setName("name3");
        employee3.setId(3);
        employee3.setSalary(14800D);

        List<Employee> employees = new LinkedList<>();
        employees.add(employee1);
        employees.add(employee2);
        employees.add(employee3);
        map.put("employees",employees);

我们接下来要实现的效果就是用迭代器,将这三列数据在HTML页面上显示出来

	<table border="1px">
        <tr>
            <td>姓名</td>
            <td>工号</td>
            <td>薪资</td>
        </tr>
        <tr th:each="emp : ${employees}">
            <td th:text="${emp.name}"></td>
            <td th:text="${emp.id}"></td>
            <td th:text="${emp.salary}"></td>
        </tr>
    </table>

效果:
在这里插入图片描述
在本例中,th:each作用于tr标签上,将使整个tr标签进行迭代-----即每一次迭代都会生成一个当前标签

Thymeleaf还支持获取迭代状态,这就需要给th:each多传入一个参数,来获取当前的迭代状态:

		<tr th:each="emp,iterState : ${employees}">
           ...
        </tr>

在这里,多传入了一个参数iterState。迭代器的状态信息将保存在iterState(名字任取)对象中,该对象具有以下属性:

  • index,当前下标(从0开始)
  • count,当前下标(从1开始)
  • size,总记录数
  • current,当前迭代出的对象
  • even/odd,当前迭代的下标是偶数还是奇数(从1开始算,返回布尔值)
  • first,当前是否为第一个元素
  • last,当前是否为最后一个元素

示例代码如下:

	<table border="1px">
        <tr>
            <td>序号</td>
            <td>奇偶性</td>
            <td>姓名</td>
            <td>工号</td>
            <td>薪资</td>
        </tr>
        <tr th:each="emp,iterState : ${employees}">
            <td th:text="${iterState.count}"></td>
            <td th:text="${iterState.even} ? '偶数' : '奇数'"></td>
            <td th:text="${emp.name}"></td>
            <td th:text="${emp.id}"></td>
            <td th:text="${emp.name}"></td>

        </tr>
    </table>

效果:
在这里插入图片描述

2.4.4 条件判断

  • th:if作用在标签上,如果表达式成立,则该标签显示;不成立,则标签不显示。表达式成立的条件:

    • 值非空且:
      – boolean类型的值,且值为true
      – 数字类型,且值不为0
      – 字符类型,且不为’0’
      – 字符串类型,且不为空,不为"false",“off”,“no”
      – 如果不是布尔、数字、字符、字符串,也返回true
  • th:unless与th:if完全相反

    <p th:if="${employee.id} == 1">工号为1时显示:老板好</p>
    <p th:unless="${employee.id} == 1">工号为其他时显示:你好</p>
    
    th:unless="${employee.id} == 1"等价于th:if="not (${employee.id} == 1)"[注意优先级问题]
    
  • th:switch、th:case

	<table border="1px">
        <tr>
            <td>序号</td>
            <td>奇偶性</td>
            <td>姓名</td>
            <td>工号</td>
            <td>薪资</td>
            <td>职位</td>
        </tr>
        <tr th:each="emp,iterState : ${employees}">
            <td th:text="${iterState.count}"></td>
            <td th:text="${iterState.even} ? '偶数' : '奇数'"></td>
            <td th:text="${emp.name}"></td>
            <td th:text="${emp.id}"></td>
            <td th:text="${emp.salary}"></td>
            <div th:switch="${emp.id}">
                <td th:case="1">老板</td>
                <td th:case="2">经理</td>
                <td th:case="*">普通职员</td>
            </div>

        </tr>
    </table>

效果:
在这里插入图片描述
和th:if一样,满足条件的标签才会被显示,不满足条件会直接被剔除,这一点通过查看源代码不难发现:
在这里插入图片描述

2.4.5 片段声明与引入

准备工作:在templates/public目录下新创建public.html用于存放公共代码片段。

  • 使用th:fragment声明公共片段
    声明:

    	<div th:fragment="public_fragment">
            这是th:fragment声明的公共片段
        </div>
    

    引入:

    <div th:replace="public/public :: public_fragment"></div>
    
  • 使用id选择器声明片段

    	<div id="public_id">
            这是用id选择器声明的片段
        </div>
    

    引入

    <div th:replace="public/public :: #public_id"></div>
    
  • th:replace和th:insert区别
    引入片段有两种方式:th:replace和th:insert。从字面意思不难看出一个是插入,一个是替换。

    <h1 th:insert="public/public :: #public_id"></h1>
    <h1 th:replace="public/public :: #public_id"></h1>
    

效果:
在这里插入图片描述
看一下源码:
在这里插入图片描述
可以看到,使用th:replace会将整个标签完全替换掉,而使用th:insert将保留使用时的标签。

2.4.6 th:object获取对象

th:object一般配合选择表达式来使用,前面在讲选择表达式的时候也说到了它的用法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值