整合静态资源与模板引擎


整合静态资源与模板引擎

1. webjars 与静态资源

⼀、spring boot 静态资源

1. 静态资源⽬录

SpringBoot 默认配置下,提供了以下⼏个静态资源⽬录:

⽬录 配置信息
/static classpath:/static/
/public classpath:/public/
/resources classpath:/resources/
/META-INF/resources classpath:/META-INF/resources/

当然,可以通过 spring.resources.static-locations 配置指定静态⽂件的位置。但是要特别注意,⼀旦⾃⼰指定了静态资源⽬录,系统默认的静态资源⽬录就会失效。所以系统默认的就已经⾜够使⽤了,尽量不要⾃定义。

#配置静态资源 spring: resources: #指定静态资源⽬录 static-locations: classpath:/mystatic/

2. favicon.ico 图标

如果在配置的静态资源⽬录中有 favicon.ico ⽂件,SpringBoot 会⾃动将其设置为应⽤图标。也就是浏览器的 tab ⻚图标。

3. 欢迎⻚⾯

SpringBoot ⽀持静态和模板欢迎⻚,它⾸先在静态资源⽬录查看 index.html ⽂件做为⾸⻚,若未找到则去查找 index 模板⽂件。

4. 示例

⼆、使⽤ WebJars 管理 css&js

为什么使⽤ WebJars?

显⽽易⻅,因为简单。但不仅是依赖这么简单:

  • 清晰的管理 web 依赖
  • 通过 Maven, Gradle 等项⽬管理⼯具就可以下载 web 依赖
  • 解决 web 组件中传递依赖的问题以及版本问题
  • ⻚⾯依赖的版本⾃动检测功能

WebJars 是将这些通⽤的 Web 前端资源打包成 Java 的 Jar 包,然后借助 Maven ⼯具对其管理,保证这些 Web 资源版本唯⼀性,升级也⽐较容易。

关于 Wsebjars 资源,有⼀个专⻔的⽹站https://www.webjars.org/,我们可以到这个⽹站上找到⾃⼰需要的资源,在⾃⼰的⼯程中添加⼊ maven 依赖,即可直接使⽤这些资源了。

1. pom 中引⼊依赖

我们可以从 WebJars 官⽅查看 maven 依赖,如下图

例如将 bootstrap 和 jquery 引⼊ pom ⽂件中

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>jquery</artifactId>
    <version>3.6.0</version>
</dependency>
<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>bootstrap</artifactId>
    <version>5.1.3</version>
</dependency>

2. 访问引⼊的 CSS 和 JS ⽂件

在 html 内访问静态资源可以使⽤如下⽅式:

<link rel="stylesheet" href="/webjars/bootstrap/5.1.3/css/bootstrap.min.css">
<script src="/webjars/jquery/3.6.0/jquery.min.js "></script>
<script src="/webjars/bootstrap/5.1.3/js/bootstrap.min.js"></script>

三、⾃动检测依赖的版本

从 Spring 4.2 开始,加⼊ webjars-locator 组件,就不需要在 html 添加依赖的时候填写版本。

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>webjars-locator</artifactId>
    <version>0.45</version>
</dependency>

引⼊ webjars-locator 值后可以省略版本号:

<link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.min.css">
<script src="/webjars/jquery/jquery.min.js "></script>
<script src="/webjars/bootstrap/js/bootstrap.min.js"></script>

好处是:当你升级 webjar 版本的时候,就不⽤每个引⼊ webjar 的⽂件都修改⼀遍版本号。

四、测试

2. 模板引擎选型与未来趋势

⼀、Java web 开发经历的⼏个阶段

1.1 JSP 开发阶段

现在仍然有很多企业项⽬使⽤ JSP 开发。可以说 JSP 就是⻚⾯端的 Servlet,JSP ⽂件糅合了三种元素: Java 代码、动态的数据、HTML 代码结构。

从抽象层次来看,Java 代码部分不仅⽤来组织数据,还被⽤来控制 HTML ⻚⾯结构。这样在层次划分上是含糊不清的。当然企业可以通过规范的⽅式去限制,不允许在 JSP ⻚⾯写 Java 代码,但这只是规范层⾯的事,实际怎样⽆法控制。

1.2 使⽤ Java 模板引擎

在这个阶段就出现了 Freemarker、Velocity 这样的严格数据模型与业务代码分离的模板引擎,实现了严格的 MVC 分离。

模板引擎的另外⼀个好处就是:宏定义或者说是组件模板,⽐ JSP 标签好⽤,极⼤的减少了重复⻚⾯组件元素的开发。另外,相对于 JSP ⽽⾔,模板引擎的开发效率会更⾼。我们都知道,JSP 在第⼀次执⾏ 的时候需要转换成 Servlet 类,开发阶段进⾏功能调适时,需要频繁的修改 JSP ,每次修改都要编译和转 换,那么我们浪费在程序编译的时间有多少。

但是 Java 模板引擎,仍然是使⽤的服务器端的渲染技术,也就是没有办法将 HTML ⻚⾯和后台服务层⾯全⾯解耦,这就要求前端⼯程师和后端⼯程师在同⼀个项⽬结构下⼯作,⽽且前端⼯程师及其依赖于后端的业务数据,⻚⾯⽆法脱离于后端请求数据在浏览器独⽴运⾏。

1.3 前端⼯程化

在 Ajax 和 Nodejs 相继出现之后,可以说为前端的发展带来了⾰命性的变化,前端可以做⾃⼰的⼯程化实践。这些新的前端技术通常是“所⻅即所得”,写完的代码可以直接在浏览器上查看,将前端后端的串⾏化⼯作模式转变为并⾏⼯作的模式。前端专注于布局、美化,后端专注于业务。专业的⼈越来越专业, ⼯作效率也更⾼。

随着 Vue、Angularjs、React 的⼤⾏其道,开始实现真正的前后端分离技术。前端的⼯程师负责⻚⾯的美化与结构,后端⼯程师可以专注于业务的处理。

⼆、Java 模板引擎的选型

常⻅的模板引擎有 Freemarker、Thymeleaf、Velocity 等。

SpringBoot ⽬前官⽅集成的框架只有 freemarker 和 Thymeleaf。

Thymeleaf:

Thymeleaf 的最⼤优点也是它的最⼤的缺点,就是它使⽤静态 html 嵌⼊标签属性,浏览器可以直接打开模板⽂件,便于前后端联调。也就是贴近于“所⻅即所得”。但是也正是因为,thyme 使⽤标签属性去放数据,也导致它的语法违反了程序员对于 html 的理解。另外 Thymeleaf 的性能⼀直为⼈所诟病。

对⼀个对象数组遍历的代码:

Thymeleaf 代码:

<tr th:each="item : ${users}">
  <td th:text="${item.userId}"></td>
  <td th:text="${item.username}"></td>
  <td th:text="${item.password}"></td>
  <td th:text="${item.email}"></td>
  <td th:text="${item.mobile}"></td>
</tr>

FreeMarker 代码:

<#list users as item>
  <tr>
    <td>${item.userId}</td>
    <td>${item.username}</td>
    <td>${item.password}</td>
    <td>${item.email}</td>
    <td>${item.mobile}</td>
  </tr>
</#list>

很明显 FreeMarker 更符合开发⼈员对于 HTML 的使⽤规范,将展示内容放在标签内,⽽不是作为标签属性存在。ThymeLeaf2.0 的性能为⼈所诟病,Thymeleaf3.0 虽然有所改善,但是没有颠覆性的变化。 综上所述,⽬前为⽌如果使⽤ Java 模板引擎,⽐较推荐 Freemarker。当然,去学 Vue、Angularjs、 Reactjs,不要⽤纯 Java 模板引擎,这些东⻄⽤得会越来越少。只是有的公司和⽼项⽬,依然还在⽤ JSP、Java 模板引擎这些技术。

可以去百度指数看⼀下,各种技术的发展和⽕爆程度。

3. Web 应⽤开发之整合 Freemarker

⼀、Freemarker 简介

FreeMarker 是⼀个模板引擎,⼀个基于模板⽣成⽂本输出的通⽤⼯具,使⽤纯 Java 编写。⼀般对 FreeMarker 第⼀印象是⽤来替代 JSP 的,但是与 JSP 不同的是 FreeMarker 模板可以在 Servlet 容器之外使⽤。可以使⽤它们来⽣成电⼦邮件、 配置⽂件、 XML 映射等。或者可以直接⽣成 HTML ⽂件,以及其他的⽂件,⽤来做代码⾃动⽣成的⼯具。

Freemarker 作为⻚⾯模板引擎的核⼼能⼒在于,将以 HTML 为基础的模板中的相关语法占位符⽤数据进⾏填充,填充之后形成可以被浏览器渲染的 HTML ⽂件。

⼆、整合

⾸先通过 maven 坐标的⽅式将 freemarker 引⼊到项⽬中来,因为 freemarker 是 Spring Boot ⽗项⽬⽀持的模板引擎,所以不⽤加版本号,版本由⽗项⽬统⼀管理。

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

在 application.yml 全局配置⽂件中进⾏如下的配置

spring:
  freemarker:
    cache: false # 缓存配置 开发阶段应该配置为false 因为经常会改
    suffix: .ftl # 模版⽂件后缀名
    charset: UTF-8 # ⽂件编码
    template-loader-path: classpath:/templates/

三、代码测试

新建 freemarker 模板⽂件,通过 controller 将 article 数据返回过来,并将查询结果 List 返回给前端 FreeMarker 模板⻚⾯,进⾏数据填充。

TemplateController.java 代码

@Controller
@RequestMapping("/template")
public class TemplateController {
    @GetMapping("/freemarker")
    public String freemarkerIndex(Model model) {
        List<Article> articles = Arrays.asList(
                new Article(1, "张三", "Java")
               , new Article(2, "张三丰", "Spring")
               , new Article(3, "张三⻛", "SpringBoot")
       );
        model.addAttribute("articles", articles);
        System.out.println(articles);
        //模版名称,实际的⽬录为:resources/templates/freemarker-demo.ftl
        return "freemarker-demo";
   }
}

模板⻚⾯代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initialscale=1.0">
    <title>Freemarker⻚⾯</title>
    <link rel="stylesheet"
href="/webjars/bootstrap/css/bootstrap.min.css">
</head>
<body>
<div class="container">
    <table class="table table-success table-hover">
        <tr>
            <td>id</td>
            <td>作者</td>
            <td>标题</td>
        </tr>
        <#list articles as article>
            <tr>
                <td>${article.id}</td>
                <td>${article.author}</td>
                <td>${article.title}</td>
            </tr>
        </#list>
    </table>
</div>
<script src="/webjars/jquery/jquery.min.js "></script>
<script src="/webjars/bootstrap/js/bootstrap.min.js"></script>
</body>
</html>

运⾏效果

四、推荐

如果想进⼀步学习 freemarker 语法,请参考: http://freemarker.foofun.cn/index.html

4. Web 应⽤开发之整合 Thymeleaf

⼀、Thymeleaf 简介

Thymeleaf 是⼀个服务器端 Java 模板引擎,能够处理 HTML、XML、CSS、JAVASCRIPT 等模板⽂ 件。Thymeleaf 模板可以直接当作静态原型来使⽤,它主要⽬标是为开发者的开发⼯作流程带来优雅的⾃然模板,也是 Java 服务器端 HTML5 开发的理想选择。

⼆、准备⼯作-IDEA 设置

在开始使⽤ ThymeLeaf 作为模板引擎进⾏⻚⾯开发之前,我们有必要对 IDEA 进⾏⼀些设置。这些设置帮助 IDEA 更好的识别 ThymeLeaf 语法,增强我们的开发体验。

  • 安装 ThymeLeaf 插件,并使其⽣效(在绝⼤多数的 IDEA 版本该插件都是默认安装并⽣效的)

  • 去掉变量表达式识别检查,会造成变量红⾊下划线,影响开发体验

三、集成

使⽤ Maven 坐标将 thymeleaf 引⼊到项⽬中

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

对 thymeleaf 模板进⾏配置

spring:
  thymeleaf:
    cache: false # 启⽤缓存:建议⽣产开启
    check-template-location: true # 检查模版是否存在
    enabled: true # 是否启⽤
    encoding: UTF-8 # 模版编码
    excluded-view-names: # 应该从解析中排除的视图名称列表(⽤逗号分隔)
    mode: HTML5 # 模版模式
    prefix: classpath:/templates/ # 模版存放路径
    suffix: .html # 模版后缀

四、Hello ThymeLeaf

查询⼀个 articles ⽂章列表,并返回模板名称,由 Spring 根据名称找到模板进⾏⻚⾯渲染。

controller 代码

@Controller
@RequestMapping("/template")
public class TemplateController {
    @GetMapping("/thymeleaf")
    public String thymeleafIndex(Model model) {
        List<Article> articles = Arrays.asList(
                new Article(1, "张三", "Java")
               , new Article(2, "张三丰", "Spring")
               , new Article(3, "张三⻛", "SpringBoot")
       );
        model.addAttribute("articles", articles);
        return "thymeleaf-demo";
   }
}

thymeleaf-demo.html 模板⻚代码

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="UTF-8" />
    <title>Title</title>
    <link
      rel="stylesheet"
      th:href="@{/webjars/bootstrap/css/bootstrap.min.css}"
    />
  </head>
  <body>
    <div class="container">
      <table class="table table-dark table-hover">
        <tr>
          <td>id</td>
          <td>作者</td>
          <td>标题</td>
        </tr>
        <tr th:each="item : ${articles}">
          <td th:text="${item.id}"></td>
          <td th:text="${item.author}"></td>
          <td th:text="${item.title}"></td>
        </tr>
      </table>
    </div>
  </body>
</html>

运⾏效果

5. Thymeleaf 基础语法讲解

⼀、基础语法

变量表达式 ${}

使⽤⽅法:直接使⽤ th:xx = “${}” 获取对象属性 。例如:articles 是⼀个集合,集合中的元素就是⼀个对 象,articles[0] 表示集合中第⼀个对象。

<!-- Thymeleaf 基础语法1: 变量表达式 ${}-->
<div class="row">
  <div class="col-4">
    <label for="input1" class="form-label">id</label>
    <input
      type="text"
      class="form-control"
      id="input1"
      th:value="${articles[0].id}"
    />
  </div>
  <div class="col-4">
    <label for="input2" class="form-label">author</label>
    <input
      type="text"
      class="form-control"
      id="input2"
      th:value="${articles[0].author}"
    />
  </div>
  <div class="col-4">
    <label for="input3" class="form-label">title</label>
    <input
      type="text"
      class="form-control"
      id="input3"
      th:value="${articles[0].title}"
    />
  </div>
</div>

选择变量表达式 *{}

使⽤⽅法:⾸先通过 th:object 获取对象,然后使⽤ th:xx = “*{}” 获取对象属性。显示效果和上⾯的例⼦是⼀样的。

<!-- Thymeleaf 基础语法2: 选择变量表达式 *{}-->
<div class="row" th:object="${articles[1]}">
  <div class="col-4">
    <label for="input4" class="form-label">id</label>
    <input type="text" class="form-control" id="input4" th:value="*{id}" />
  </div>
  <div class="col-4">
    <label for="input5" class="form-label">author</label>
    <input type="text" class="form-control" id="input5" th:value="*{author}" />
  </div>
  <div class="col-4">
    <label for="input6" class="form-label">title</label>
    <input type="text" class="form-control" id="input6" th:value="*{title}" />
  </div>
</div>

链接表达式 @{}

使⽤⽅法:通过链接表达式@{}直接拿到应⽤路径,然后拼接静态资源路径。例如:

<link rel="stylesheet" th:href="@{/webjars/bootstrap/css/bootstrap.min.css}" />
<script th:src="@{/webjars/jquery/jquery.min.js} "></script>
<script th:src="@{/webjars/bootstrap/js/bootstrap.min.js}"></script>

html ⻚⾯实际引⼊效果如下(这种⽅式会将 webjars 的版本号暴露出来,⼀定程度上造成安全问题,所以使⽤ webjars 就别⽤链接表达式):

其它表达式

在基础语法中,默认⽀持字符串连接、数学运算、布尔逻辑和三⽬运算等。例如:

<!-- Thymeleaf 基础语法4: 字符串连接、数学运算、布尔逻辑、三⽬运算符等-->
<br />
<div
  th:text="${'我是:' + (articles[2].author != null ? articles[2].author : '没有内容' )}"
></div>

以上 diamante 运⾏效果

⼆、迭代循环

想要遍历 List 集合很简单,配合 th:each 即可快速完成迭代。但是我们通常有⼀些需求,在集合的迭代过程还可以获取状态变量。状态变量可⽤于获取集合的下标/序号、总数、是否为单数/偶数⾏、是否为第⼀个/最后⼀个。例如:

<table class="table table-hover">
  <tr>
    <td>下标</td>
    <td>序号</td>
    <td>id</td>
    <td>作者</td>
    <td>标题</td>
  </tr>
  <tr
    th:each="item,stat : ${articles}"
    th:class="${stat.even} ? 'even' : 'odd'"
  >
    <td th:text="${stat.index}"></td>
    <td th:text="${stat.count}"></td>
    <td th:text="${item.id}"></td>
    <td th:text="${item.author}"></td>
    <td th:text="${item.title}"></td>
  </tr>
</table>

迭代下标变量⽤法:

状态变量定义在⼀个 th:每个属性和包含以下数据:

  • index: 当前迭代索引,从 0 开始。这是索引属性。
  • count: 当前迭代序号,从 1 开始。这是序号属性。
  • size: 元素的总量迭代变量。这是⼤⼩属性。
  • current: 变量为每个迭代,当前正迭代的元素。
  • even/odd: 是否当前迭代是奇数还是偶数,布尔属性。
  • first: 是否第⼀个当前迭代,布尔属性。
  • last: 是否最后⼀个当前迭代,布尔属性。

显示效果如下:

其中表格隔⾏换⾊,即奇数⾏换⾊,是通过 stat.even 实现的。为奇数⾏单独设置背景颜⾊

<style>
    .odd {
        background-color: #7d7d7d;
   }
</style>

三、条件判断

条件判断通常⽤于动态⻚⾯的初始化,例如:

<div th:if="${articles}">
  <h4>⽂章列表存在</h4>
</div>

条件判断表达式可以是如下类型:

  • boolean 类型并且值是 true, 返回 true
  • 数值类型并且值不是 0, 返回 true
  • 字符类型(Char)并且值不是 0, 返回 true
  • String 类型并且值不是 “false”, “off”, “no”, 返回 true
  • 不是 boolean, 数值, 字符, String 的其他类型, 返回 true
  • 对象值是 null, 返回 false

如果想取反则使⽤ unless 例如:

<div th:unless="${users}">
  <h4>⽤户列表暂⽆</h4>
</div>

6. Thymeleaf 内置对象与⼯具类

⼀、内置对象

官⽅⽂档:Thymeleaf 3.0 基础对象

七⼤基础对象:

  • ${#ctx}: 上下⽂对象,可⽤于获取其它内置对象。
  • ${#param}: 上下⽂参数变量。
  • ${#locale}: 上下⽂区域语⾔设置对象。
  • ${#request}: HttpServletRequest 对象。
  • ${#response}: HttpServletResponse 对象。
  • ${#session}: HttpSession 对象。
  • ${#servletContext}: ServletContext 对象。

⽤法示例

为了演示数据,我们在后端向 thymeleaf 模板传参的时候,使⽤不同的对象容器。并注意下图中的参数 名称:name1、name2、name3、name4。

controller 代码

@GetMapping("/thymeleaf1")
public String index(@RequestParam String name1, HttpServletRequest request, Model model) {
    List<Article> articles = Arrays.asList(
            new Article(1, "张三", "Java")
           , new Article(2, "张三丰", "Spring")
           , new Article(3, "张三⻛", "SpringBoot")
   );
    request.setAttribute("name2", "world");
    request.getSession().setAttribute("name3", "aaa");
    request.getServletContext().setAttribute("name4", "bbb");
    model.addAttribute("articles", articles);
    return "thymeleaf-demo1";
}

⻚⾯代码

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="UTF-8" />
    <title>Thymeleaf⻚⾯</title>
    <!--   <link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.min.css">-->
    <link
      rel="stylesheet"
      th:href="@{/webjars/bootstrap/css/bootstrap.min.css}"
    />
    <style>
      .odd {
        background-color: #7d7d7d;
      }
    </style>
  </head>
  <body>
    <div class="container overflow-hidden">
      <h1>ThymeLeaf内置对象</h1>
      <br />语⾔国家:
      <span
        th:text="${#locale.getLanguage() + '_' + #locale.getCountry()}"
      ></span>
      <br />param: <span th:text="${param.name1}"></span> <br />request:
      <span th:text="${name2}"></span> <br />session:
      <span th:text="${session.name3}"></span> <br />application:<span
        th:text="${application.name4}"
      ></span>
      <br />session包含name3属性么(如不包含显示zoo):<span
        th:text="${session.name3}?:('zoo')"
      ></span>
      <br />session包含属性数量:<span th:text="${session.size()}"></span>
      <br />session是空的么:<span th:text="${session.isEmpty()}"></span>
    </div>
    <script th:src="@{/webjars/jquery/jquery.min.js} "></script>
    <script th:src="@{/webjars/bootstrap/js/bootstrap.min.js}"></script>
  </body>
</html>

访问:http://localhost:8080/template/thymeleaf1?name1=hello

⼆、 常⽤的⼯具类:

官⽅⽂档: Thymeleaf 3.0 ⼯具类

  • #strings:字符串⼯具类
  • #lists:List ⼯具类
  • #arrays:数组⼯具类
  • #sets:Set ⼯具类
  • #maps:常⽤ Map ⽅法
  • #objects:⼀般对象类,通常⽤来判断⾮空
  • #bools:常⽤的布尔⽅法
  • #execInfo:获取⻚⾯模板的处理信息
  • #messages:在变量表达式中获取外部消息的⽅法,与使⽤#{…}语法获取的⽅法相同
  • #uris:转义部分 URL / URI 的⽅法
  • #conversions:⽤于执⾏已配置的转换服务的⽅法
  • #dates:时间操作和时间格式化等
  • #calendars:⽤于更复杂时间的格式化
  • #numbers:格式化数字对象的⽅法
  • #aggregates:在数组或集合上创建聚合的⽅法
  • #ids:处理可能重复的 id 属性的⽅法

⽤法举例:

date ⼯具类之⽇期格式化

使⽤默认的⽇期格式 (toString ⽅法) 并不是我们预期的格式:Mon Dec 03 23:16:50 CST 2021

此时可以通过时间⼯具类 #dates 来对⽇期进⾏格式化:2021-12-03 23:16:50

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

⾸字⺟⼤写

${#strings.capitalizeWords(str)}

list ⽅法

/* * 计算list集合中元素数量 */ ${#lists.size(list)} /* * 检查集合是否是空的 */
${#lists.isEmpty(list)}

7. 公共⽚段(标签)与内联 JS

⼀、⽚段表达式(标签) ~{}

⽚段表达式的使⽤过程,有点像我们平时代码开发过程中的:共⽤函数抽取。

确定哪些代码可重⽤

下⾯的 head 标签⽚段在很多的⻚⾯都存在,并且⼤部分的内容是⼀致的,加⼊我们希望 head 标签⾥⾯的内容能在各个⻚⾯内重⽤,该怎么办?我们本节就带着⼤家来解决组件代码重⽤的问题。

<head>
  <meta charset="UTF-8" />
  <title>Title</title>
  <link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.min.css" />
  <style type="text/css">
    .odd {
      background-color: #7d7d7d;
    }
  </style>
</head>

定制可重⽤代码⽚段

⾸先通过 th:fragment 定制代码⽚段 ,通常将项⽬⾥⾯经常重⽤的代码抽取为代码⽚段(标签),代码⽚段可以设置参数:title、version

<!-- /templates/common/head.html-->
<html lang="en" xmlns:th="http://www.thymeleaf.org">
  <head th:fragment="static(version,title)">
    <meta charset="UTF-8" />
    <title th:text="${title}"></title>
    <link
      rel="stylesheet"
      th:href="'/webjars/bootstrap/'+ ${version} + '/css/bootstrap.min.css'"
    />
    <style type="text/css">
      .odd {
        background-color: #7d7d7d;
      }
    </style>
  </head>
</html>

引⽤可重⽤代码⽚段

然后在不同的⻚⾯引⽤该⽚段,达到代码重⽤的⽬的,可以传递参数 version、title

<head th:replace="~{common/head::static('4.5.0','⻚⾯标题')}"></head>

最终重⽤代码组合效果如下:

⽚段表达式是 Thymeleaf 的特⾊之⼀,细粒度可以达到标签级别,这是 JSP ⽆法做到的。

⽚段表达式拥有三种语法:

  • ~{ viewName }表示引⼊完整⻚⾯
  • ~{ viewName ::selector} 表示在指定⻚⾯寻找⽚段 其中 selector 可为⽚段名、jquery 选择器等, 即可以在⼀个 html ⻚⾯内定义多个⽚段
  • ~{ ::selector}表示在当前 html ⻚查找代码⽚段

⼆、多种⽚段组合⽅式

在实际使⽤中,我们往往使⽤更简洁的表达,去掉表达式外壳直接填写⽚段名。例如:

<div th:replace="common/head::static"></div>
<div th:insert="common/head::static"></div>
<div th:include="common/head::static"></div>

关于 thymeleaf th:replace th:include th:insert 的区别

  • th:replace :不要⾃⼰的主标签,保留 th:fragment 的主标签

  • th:insert :保留⾃⼰的主标签,保留 th:fragment 的主标签。

  • th:include :保留⾃⼰的主标签,不要 th:fragment 的主标签。(官⽅ 3.0 后不推荐)

值得注意的是,使⽤替换路径 th:replace 开头请勿添加斜杠/,避免部署运⾏的时候出现路径报错。 (因为默认拼接的路径为 spring.thymeleaf.prefix = classpath:/templates/)

⼆、内联语法

我们之前所讲的内容都是在 html 标签上使⽤的 thymeleaf 的语法,那么如果我们需要在 javascript ⾥⾯获取变量的值(使⽤之前所讲的表达式),该怎么做?

答:标准格式为:[[${expression}]] ,可以读取服务端变量,也可以调⽤内置对象的⽅法。例如获取⽤户变量和应⽤路径:

<script th:inline="javascript">
  var user = [[${articles[0]}]];
  var APP_PATH = [[${#request.getContextPath()}]];
  var LANG_COUNTRY = [[${#locale.getLanguage()+'_'+#locale.getCountry()}]];
</script>

HTML ⻚⾯使⽤内联语法结果如下:

标签(代码⽚段)内引⼊的 JS ⾥⾯能使⽤内联表达式吗?答:不能!内联表达式仅在⻚⾯⽣效,因为 Thymeleaf 只负责解析⼀级视图,不能识别外部标签 JS ⾥⾯的表达式。


文章作者: Syhan
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Syhan !
评论
  目录