1.简介
在本教程中,我们将看一下Thymeleaf中的变量。我们将创建一个Spring Boot示例,该示例将获取Ba文章列表并将其显示在Thymeleaf HTML模板中。
2. Maven依赖
要使用Thymeleaf,我们需要添加spring-boot-starter-thymeleaf
和spring-boot-starter-web
依赖项:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
3. Web控制器
首先,我们将创建一个具有GET端点的Web控制器,该端点将返回包含Ba文章列表的页面。
@GetMapping
注释的方法将采用一个参数– Model
。它包含可在Thymeleaf模板中进一步使用的所有全局变量。在我们的例子中,模型只有一个参数-文章列表。
Article
类将包含两个String
字段, name
和url
:
public class Article {
private String name;
private String url;
// constructor, getters and setters
}
我们控制器方法的返回值应该是所需Thymeleaf模板的名称。该名称应对应于src/resource/template
目录中的HTML文件。在我们的例子中,它将是src/resource/template/articles-list.html
。
让我们快速看一下我们的Spring控制器:
@Controller
@RequestMapping("/api/articles")
public class ArticlesController {
@GetMapping
public String allArticles(Model model) {
model.addAttribute("articles", fetchArticles());
return "articles-list";
}
private List<Article> fetchArticles() {
return Arrays.asList(
new Article(
"Introduction to Using Thymeleaf in Spring",
"https://www.baeldung.com/thymeleaf-in-spring-mvc"
),
// a few other articles
);
}
}
运行该应用程序后,将在http://localhost:8080/articles
提供articles页面。
4. Thymeleaf模板
现在,让我们进入Thymeleaf HTML模板。它应该具有标准的HTML文档结构,仅带有附加的Thymeleaf命名空间定义:
<html xmlns:th="http://www.thymeleaf.org">
我们将在其他示例中将其用作模板,在这里我们将仅替换<main>
标记的内容:
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Thymeleaf Variables</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<main>
...
</main>
</body>
</html>
5.定义变量
我们可以通过两种方式在Thymeleaf模板中定义变量。第一种选择是在遍历数组时采用单个元素:
<div th:each="article : ${articles}">
<a th:text="${article.name}" th:href="${article.url}"></a>
</div>
结果,我们将得到一个<div>
其中包含几个<a>
元素,它们与articles
变量中的文章数相对应。
另一种方法是基于另一个变量定义一个新变量。例如,我们可以采用Articles数组的第一个元素:
<div th:with="firstArticle=${articles[0]}">
<a th:text="${firstArticle.name}" th:href="${firstArticle.url}"></a>
</div>
或者我们可以创建一个仅包含文章名称的新变量:
<div th:each="article : ${articles}", th:with="articleName=${article.name}">
<a th:text="${articleName}" th:href="${article.url}"></a>
</div>
在上面的示例中, ${article.name}
和${articleName}
片段是可替换的。
也可以定义多个变量。例如,我们可以创建两个单独的变量来保存商品名称和URL:
<div th:each="article : ${articles}" th:with="articleName=${article.name}, articleUrl=${article.url}">
<a th:text="${articleName}" th:href="${articleUrl}"></a>
</div>
6.变量范围
在控制器中传递给Model
变量具有全局作用域。这意味着它们可以在我们的HTML模板的每个位置使用。
另一方面,HTML模板中定义的变量具有局部作用域。它们只能在定义它们的元素范围内使用。
例如,下面的代码是正确的,因为<a>
元素位于firstDiv
:
<div id="firstDiv" th:with="firstArticle=${articles[0]}">
<a th:text="${firstArticle.name}" th:href="${firstArticle.url}"></a>
</div>
另一方面,当我们尝试在另一个div
firstArticle
时:
<div id="firstDiv" th:with="firstArticle=${articles[0]}">
<a th:text="${firstArticle.name}" th:href="${firstArticle.url}"></a>
</div>
<div id="secondDiv">
<h2 th:text="${firstArticle.name}"></h2>
</div>
我们会在编译时得到一个异常,说firstArticle
为null
:
org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'name' cannot be found on null
这是因为<h2>
firstDiv,
定义的变量,该变量超出范围。
如果我们仍然需要使用firstArticle
内部变量secondDiv
,我们需要再次定义它secondDiv
或包装这两个div
在一个共同的元素标记,并定义firstArticle
在里面。
7.更改变量的值
在给定范围内也可以覆盖变量的值:
<div id="mainDiv" th:with="articles = ${ { articles[0], articles[1] } }">
<div th:each="article : ${articles}">
<a th:text="${article.name}" th:href="${article.url}"></a>
</div>
</div>
在上面的示例中,我们重新定义了articles
变量,使其仅具有两个前元素。
请注意,在mainDiv,
articles
变量仍将在控制器中传递其原始值。
8.结论
在本教程中,我们学习了如何在Thymeleaf中定义和使用变量。
0 评论