SpringBoot-09-Thymeleaf

比jsp好用一点,因为jsp每次都要编译成servlet,效率实在太低了。但是现在也没太多人用了,毕竟都是前后端分离,但是作为学习路线,还是不跳过的好,简单了解一下。

快速使用

新建SpringBoot项目的时候除了勾选Spring Web,还要勾选Thymeleaf,其实也就是pom文件里多一个Thymeleaf的起步依赖,然后就可以用了。

首先还是需要一个controller

@Controller("myController")
public class MyController {

    @RequestMapping("/message")
    public ModelAndView getMessage(ModelAndView modelAndView) {
        modelAndView.addObject("message", "展示后台数据");
        modelAndView.setViewName("message");
        return modelAndView;
    }
}

然后现在就不像之前使用jsp那么麻烦了,直接在templates目录下新建message.html就可以了。

message.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--    thymeleaf模板引擎的页面必须通过中央调度器-->
    <h3 th:text="${message}">展示前端数据</h3>
</body>
</html>

只需要在命名空间中引入thymeleaf就可以正常使用了,所有功能基本都要th:开头。模板引擎的一个好处就是当可以拿到message的数据就替换“展示前端数据”这句话, 如果拿不到就不替换,不会什么都不显示。

关闭页面缓存

上面的例子和之前不太一样的是,没有配视图解析器,那我们没有加.html后缀,SpringBoot是怎么识别的?其实已经配了,用的是默认的值:

所以自己可加可不加,后续如果页面的位置需要改动的时候记得改就可以。

之前用jsp的时候我们只要在配置中这么设置就可以修改html的时候页面自动更新:

但是Thymeleaf自带的有缓存,而且默认开启,所以需要把缓存也关了才可以:

spring.thymeleaf.cache=false

这样修改html就不用重新启动项目了。

变量表达式

一种就是${},就是之前的EL表达式,用起来也比较方便;还有一种是选择变量表达式*{},感觉看起来不太直观。

@RequestMapping("/user")
public ModelAndView getUserDetail(ModelAndView modelAndView) {
    modelAndView.addObject("user", new User(1001, "张三", 23));
    modelAndView.setViewName("user");
    return modelAndView;
}

user.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>变量表达式</title>
</head>
<body>
    <h1>标准变量表达式:${}  (推荐)</h1>
    用户编号:<span th:text="${user.id}"></span><br>
    用户姓名:<span th:text="${user.name}"></span><br>
    用户年龄:<span th:text="${user.age}"></span><br>

    <h1>选择变量表达式:*{}  (不推荐)</h1>
    <div th:object="${user}">
        用户编号:<span th:text="*{id}"></span><br>
        用户姓名:<span th:text="*{name}"></span><br>
        用户年龄:<span th:text="*{age}"></span><br>
    </div>
</body>
</html>

结果:

有可能会碰到变量表达式爆红的情况,但是不影响运行结果。我现在试下来是先写controller的代码,然后再创建对应的页面,就不会爆红;但是先创建页面,再写代码,就会爆红,但最后页面都能拿到数据,还挺玄学的。

路径表达式

格式:@{…}。为了后续演示方便,把context-path设为了/thymeleaf

controller中直接将/url请求转发到url.html:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>URL路径表达式</title>
</head>
<body>
    <h1>URL路径表达式@{...}</h1>
    <h2>绝对路径</h2>
    <a th:href="@{www.baidu.com}">绝对路径,跳转到百度</a><br>
    <h2>相对路径</h2>
    <a th:href="@{/user}">相对路径,/ 代表项目上下文</a>
</body>
</html>

可以直接看网页源代码,看路径表达式最后变成什么样子了:

这个时候www.baidu.com是没有带协议的,下面点一下:

可以看到还是用项目的上下文当前缀,也就是这里并不是绝对路径,绝对路径一定是带协议和端口号才可以的。

html中加上协议就可以正常跳转了,这个时候绝对路径和正常的超链接标签是一样的,没什么区别。

但是这个时候看/user在页面中直接变成了/thymeleaf/user,加上了项目的contexpath,点击可以正常跳转到user页面:

地址栏的url为:http://localhost:8080/thymeleaf/user

如果要跳转到另一个服务器上的另一个项目,就不能用 / 了,这只能在当前项目跳转,thymeleaf提供了另一种语法:

<h2>相对服务器根路径</h2>
<a th:href="@{~/anotherProjectContext/user}">相对服务器根路径,~代表服务器的根</a>

再看一下源代码:

点击的话地址栏的url会变为http://localhost:8080/anotherProjectContext/user

下面是带参数的写法,这个时候就体现出地址表达式的强大了,先改一下代码:

@RequestMapping("/url")
public ModelAndView getURL(ModelAndView modelAndView) {
    modelAndView.addObject("id", 1001);
    modelAndView.addObject("name", "李四");
    modelAndView.addObject("age", 24);
    modelAndView.setViewName("url");
    return modelAndView;
}

@RequestMapping("/ret")
@ResponseBody
public String getRet(Integer id, String name, Integer age) {
    return "请求路径中带的参数,id = " + id + ", name = " + name + ", age = " + age;
}
<h2>相对路径带参数</h2>
<a th:href="@{/ret(id = ${id}, name = ${name}, age = ${age})}">跳转到/ret,并且带多个参数</a>

这个时候就不需要像以前那样自己去拼字符串了,直接按这个格式写就行,下面看一下网页源代码:

可以看到thymeleaf已经帮我们拼好了,直接点是没有任何问题的:

如果觉得这种传参方式不够REST,thymeleaf也是支持REST风格的,写法如下:

@RequestMapping("/rest/{id}/{name}/{age}")
@ResponseBody
public String getRest(@PathVariable("id") Integer id,
                      @PathVariable("name") String name,
                      @PathVariable("age") Integer age) {
    return "请求路径中带的参数,id = " + id + ", name = " + name + ", age = " + age;
}
<h2>相对路径带参数REST风格</h2>
<a th:href="@{/rest/{id}/{name}/{age}(id = ${id}, name = ${name}, age = ${age})}">跳转到/rest,带多个参数</a>

当然实际也没有这么用REST风格的,这里只是演示一下参数是可以这么传递的,不用拼在url后面:

静态资源

这个问题卡了半天,首先还是要注意maven的问题,compile之后看一下classes目录下有没有你的静态资源,如果没有clean一下或者rebuild一下,参考之前的博客。

图片的路径是/static/img/…png,这里用不用th标签都可以,最起码我这个版本,这两种写法还都访问的到图片

<h2>静态资源路径</h2>
<img src="img/wallhaven-e7ypv8_1920x1080.png" alt="加载失败">
<img th:src="@{/img/wallhaven-e7ypv8_1920x1080.png}" alt="加载失败">

网上还有在配置文件中这样配的

spring.resources.static-locations=classpath:/static/
spring.mvc.static-path-pattern=/static/**

这样配的话,路径就是/static/img/…png。两种写法我这都可以。

常用标签

剩下的了解一下就行,毕竟后面也用得不多。

  • 遍历(array,List,Map都一样)

    @RequestMapping("/each/list")
    public ModelAndView eachList(ModelAndView mv) {
        List<User> userList = new ArrayList<>();
        for (int i = 0; i < 10; ++i) {
            User user = new User(100 + i, "张" + i, 20 + i);
            userList.add(user);
        }
        mv.addObject("userList", userList);
        mv.setViewName("each");
        return mv;
    }
    
    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>循环遍历List集合</title>
    </head>
    <body>
    <!--
        user 当前循环的对象变量名称
        userStat 当前循环对象状态的变量,可以不写,默认就是对象变量名+Stat
        ${userList} 当前循环的集合
    -->
    <div th:each="user, userStat : ${userList}">
        <span th:text="${userStat.size}"></span>
        <span th:text="${userStat.count}"></span>
        <span th:text="${userStat.index}"></span>
        <span th:text="${user.id}"></span>
        <span th:text="${user.name}"></span>
        <span th:text="${user.age}"></span>
    </div>
    </body>
    </html>
    
  • 条件判断

    @RequestMapping("/condition")
    public ModelAndView condition(ModelAndView modelAndView) {
        modelAndView.addObject("sex", 1);
        modelAndView.setViewName("condition");
        return modelAndView;
    }
    
    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>条件判断</title>
    </head>
    <body>
        <h1>if</h1>
        <div th:if="${sex == 1}"></div>
        <div th:if="${sex == 0}"></div>
    </body>
    </html>
    

    还有一个unless,就是括号里的条件不成立才执行,不演示了。

  • 内敛表达式

    @RequestMapping("/inline")
    public ModelAndView inline(ModelAndView mv) {
        mv.addObject("data", "inlineData");
        mv.setViewName("inline");
        return mv;
    }
    
    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>内敛表达式</title>
    </head>
    <body>
        <h1>内敛文本  th:inline="text"</h1>
        <div th:inline="text">数据:[[${data}]]</div>
        <h1>内敛脚本  th:inline="javascript"</h1>
        <script type="text/javascript" th:inline="javascript">
            function showData() {
                alert([[${data}]])
            }
        </script>
        <button onclick="showData()">展示数据</button>
    </body>
    </html>
    
  • 拼接字符串

    就不演示了,也很直观

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>拼接字符串</title>
    </head>
    <body>
        <div th:text="|共${totalPage}页,当前第${currentPage}页。|"></div>
    </body>
    </html>
    

    这样就把从后端拿到的数据直接和前端的字符串拼一块了,不用自己再用单引一段一段地拼了。

  • 内置对象

    thymeleaf内置了很多对象,和jsp一样,可以直接拿来用,但是我们用的最多的还是request,response,session这三个。thymeleaf使用这些内置对象需要在前面加 # 。

    比如我们在controller中这么写request.getSession().setAttribute(“data”, “sessionData”)。那么在html中就可以${#session.data}这样直接取出来,还是非常方便的。

    剩下的还有很多比如#dates是java.util.Date对象的实用方法,可以直接#date.format(date, pattern)。#strings是字符串对象的使用方法,可以#strings.contains() #strings.subString()。可以理解为工具类,具体用到什么再去查就可以。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值