知識庫 / Spring / Spring MVC RSS 訂閱

使用 Thymeleaf 處理 Fragment

Spring MVC
HongKong
5
02:03 PM · Dec 06 ,2025

1. 概述

在本教程中,我們將演示如何利用 Thymeleaf Fragments 重用網站的常見部分。 在設置一個非常簡單的 Spring MVC 項目後,我們將重點關注視圖。

如果您是 Thymeleaf 的新手,可以查看本站的其他文章,例如這篇介紹文章,以及關於引擎 3.0 版本的一篇文章。

2. Maven 依賴

我們需要幾個依賴項來啓用 Thymeleaf:

<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf</artifactId>
    <version>3.1.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf-spring5</artifactId>
    <version>3.1.2.RELEASE</version>
</dependency>

最新版本的 thymeleafthymeleaf-spring5 可在 Maven Central 上找到。

3. Spring 項目

3.1. Spring MVC 配置

為了啓用 Thymeleaf 並設置模板後綴,我們需要配置 MVC,包括視圖解析器和模板解析器

我們還會設置一些靜態資源的目錄:

@Bean
public ViewResolver htmlViewResolver() {
    ThymeleafViewResolver resolver = new ThymeleafViewResolver();
    resolver.setTemplateEngine(templateEngine(htmlTemplateResolver()));
    resolver.setContentType("text/html");
    resolver.setCharacterEncoding("UTF-8");
    resolver.setViewNames(ArrayUtil.array("*.html"));
    return resolver;
}

private ITemplateResolver htmlTemplateResolver() {
    SpringResourceTemplateResolver resolver
      = new SpringResourceTemplateResolver();
    resolver.setApplicationContext(applicationContext);
    resolver.setPrefix("/WEB-INF/views/");
    resolver.setCacheable(false);
    resolver.setTemplateMode(TemplateMode.HTML);
    return resolver;
}

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/resources/**", "/css/**")
      .addResourceLocations("/WEB-INF/resources/", "/WEB-INF/css/");
}

請注意,如果使用 Spring Boot,此配置可能並非必要,除非我們需要應用自定義配置。

3.2. 控制器

在這種情況下,控制器僅僅是視圖的載體。每個視圖展示不同的使用場景。

最後一個視圖加載一些通過模型傳遞的數據,並在視圖上進行顯示:

@Controller
public class FragmentsController {

    @GetMapping("/fragments")
    public String getHome() {
        return "fragments.html";
    }

    @GetMapping("/markup")
    public String markupPage() {
        return "markup.html";
    }

    @GetMapping("/params")
    public String paramsPage() {
        return "params.html";
    }

    @GetMapping("/other")
    public String otherPage(Model model) {
        model.addAttribute("data", StudentUtils.buildStudents());
        return "other.html";
    }
}

請注意,視圖名稱必須包含 “.html” 後綴,這是因為我們配置瞭解析器的方式。我們將在引用片段名稱時也指定該後綴。

4. 視圖

4.1. 簡單片段包含

首先,我們將使用重用頁面中的常見部分。

我們可以將這些部分定義為片段,要麼在隔離的文件中,要麼在共享頁面中。 在本項目中,這些可重用的部分定義在名為 fragments 的文件夾中。

有三種基本方法可以從片段中包含內容:

  1. insert – 在標籤內插入內容
  2. replace – 用定義片段的標籤替換當前標籤
  3. include – 這是一個已棄用但可能仍然出現在遺留代碼中的方法

下一個示例,fragments.html,展示了這三種方法的用法。 此 Thymeleaf 模板在文檔的 <head><body> 中添加了片段:

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Thymeleaf Fragments: home</title>
<!--/*/ <th:block th:include="fragments/general.html :: headerfiles">
        </th:block> /*/-->
</head>
<body>
    <header th:insert="fragments/general.html :: header"> </header>
    <p>Go to the next page to see fragments in action</p>
    <div th:replace="fragments/general.html :: footer"></div>
</body>
</html>

現在,讓我們來查看一個包含一些片段的頁面。它名為 general.html,它就像一個包含一些片段的完整頁面,這些片段已準備好供使用:

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head th:fragment="headerfiles">
<meta charset="UTF-8" />
<link th:href="@{/css/styles.css}" rel="stylesheet">
</head>
<body>
    <div th:fragment="header">
        <h1>Thymeleaf Fragments sample</h1>
    </div>
    <p>Go to the next page to see fragments in action</p>
    <aside>
        <div>This is a sidebar</div>
    </aside>
    <div class="another">This is another sidebar</div>
    <footer th:fragment="footer">
        <a th:href="@{/fragments}">Fragments Index</a> | 
        <a th:href="@{/markup}">Markup inclussion</a> | 
        <a th:href="@{/params}">Fragment params</a> | 
        <a th:href="@{/other}">Other</a>
    </footer>
</body>
</html>

<head> 部分僅包含一個樣式表,但我們也可以使用諸如 Bootstrap、jQuery 或 Foundation 等工具,直接使用或通過 Webjars 使用。

請注意,本模板的所有可重用標籤都具有 th:fragment 屬性,但接下來我們將看到如何包含任何其他頁面部分。

在渲染和片段包含後,返回的內容是:

<!DOCTYPE HTML>
<html>
<head>
<title>Thymeleaf Fragments: home</title>
<meta charset="UTF-8" />
<link href="/spring-thymeleaf/css/styles.css" rel="stylesheet">
</head>
<body>
    <header>
        <div>
            <h1>Thymeleaf Fragments sample</h1>
        </div>
    </header>
    <p>Go to the next page to see fragments in action</p>
    <footer>
        <a href="/spring-thymeleaf/fragments">Fragments Index</a> | 
        <a href="/spring-thymeleaf/markup">Markup inclussion</a> | 
        <a href="/spring-thymeleaf/params">Fragment params</a> | 
        <a href="/spring-thymeleaf/other">Other</a>
    </footer>
</body>
</html>

4.2. 片段標記選擇器

Thymeleaf 片段的一個重要優勢在於,我們可以僅通過簡單的選擇器獲取任何模板的片段,通過類名、ID 或直接使用標籤。

例如,本頁包含來自 general.html 文件的部分組件:一個 aside 塊和 div.another 塊:

<body>
    <header th:insert="fragments/general.html :: header"> </header>
    <div th:replace="fragments/general.html :: aside"></div>
    <div th:replace="fragments/general.html :: div.another"></div>
    <div th:replace="fragments/general.html :: footer"></div>
</body>

4.3. 參數化片段

我們可以將參數傳遞給片段,以便修改其特定部分。要做到這一點,片段必須被定義為函數調用,其中必須聲明參數列表。

在以下示例中,我們定義了一個通用表單字段的片段:

<div th:fragment="formField (field, value, size)">
    <div>
        <label th:for="${#strings.toLowerCase(field)}"> <span
            th:text="${field}">Field</span>
        </label>
    </div>
    <div>
        <input type="text" th:id="${#strings.toLowerCase(field)}"
            th:name="${#strings.toLowerCase(field)}" th:value="${value}"
            th:size="${size}">
    </div>
</div>

以下是一個使用該片段的簡單示例,其中我們傳遞參數給它:

<body>
    <header th:insert="fragments/general.html :: header"> </header>
    <div th:replace="fragments/forms.html
      :: formField(field='Name', value='John Doe',size='40')">
    </div>
    <div th:replace="fragments/general.html :: footer"></div>
</body>

以下是返回字段的外觀示例:

<div>
    <div>
        <label for="name"> <span>Name</span>
        </label>
    </div>
    <div>
        <input type="text" id="name"
        name="name" value="John Doe"
        size="40">
    </div>
</div>

4.4. 片段包含表達式

Thymeleaf 片段提供其他有趣的選項,例如支持用於 條件表達式,以確定是否包含片段

使用 Elvis 運算符,結合 Thymeleaf 提供的任何表達式(例如安全、字符串和集合),我們可以加載不同的片段。

例如,我們可以定義一個包含某些內容的片段,該內容將根據給定的條件顯示。 這可能是一個包含不同類型塊的文件:

<div th:fragment="dataPresent">Data received</div>
<div th:fragment="noData">No data</div>

以下是使用表達式加載它們的示例:

<div
    th:replace="${#lists.size(data) > 0} ? 
        ~{fragments/menus.html :: dataPresent} : 
        ~{fragments/menus.html :: noData}">
</div>

要了解更多關於 Thymeleaf 表達式的信息,請查看我們的文章這裏

4.5. 靈活佈局

以下示例也展示了使用片段的其他有趣用法,即用於渲染包含數據的表格。 這就是可重用的表格片段,包含兩個重要部分:可自定義的表頭,以及用於渲染數據的表體:

<table>
    <thead th:fragment="fields(theadFields)">
        <tr th:replace="${theadFields}">
        </tr>
    </thead>
    <tbody th:fragment="tableBody(tableData)">
        <tr th:each="row: ${tableData}">
            <td th:text="${row.id}">0</td>
            <td th:text="${row.name}">Name</td>
        </tr>
    </tbody>
    <tfoot>
    </tfoot>
</table>

當我們需要使用這張表時,可以使用 fields 函數傳入自定義表頭。表頭通過類 myFields 進行引用。表體數據通過將數據作為參數傳遞給 tableBody 函數加載:

<body>
    <header th:replace="fragments/general.html :: header"> </header>
    <table>
        <thead th:replace="fragments/tables.html
              :: fields(~{ :: .myFields})">
            <tr class="myFields">

                <th>Id</th>
                <th>Name</th>
            </tr>
        </thead>
        <div th:replace="fragments/tables.html
          :: tableBody(tableData=${data})">
        </div>
    </table>
    <div th:replace="fragments/general.html :: footer"></div>
</body>

這是最終頁面的樣子:

<body>
    <div>
        <h1>Thymeleaf Fragments sample</h1>
    </div>
    <div>Data received</div>
    <table>
        <thead>
            <tr class="myFields">

                <th>Id</th>
                <th>Name</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>1001</td>
                <td>John Smith</td>
            </tr>
            <tr>
                <td>1002</td>
                <td>Jane Williams</td>
            </tr>
        </tbody>
    </table>
    <footer>
        <a href="/spring-thymeleaf/fragments">Fragments Index</a> |
        <a href="/spring-thymeleaf/markup">Markup inclussion</a> |
        <a href="/spring-thymeleaf/params">Fragment params</a> |
        <a href="/spring-thymeleaf/other">Other</a>
    </footer>
</body>

5. 結論

在本文中,我們展示瞭如何通過使用 Thymeleaf Fragments 重用視圖組件,這是一種強大的工具,可以簡化模板管理。

我們還介紹了其他一些有趣的特性,這些特性超越了基本功能。在選擇 Thymeleaf 作為我們的視圖渲染引擎時,應充分考慮這些特性。

如果您想了解更多 Thymeleaf 功能,請務必查看我們關於 Layout Dialects 的文章。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.