1. 簡介
在本教程中,我們將學習如何使用 Thymeleaf 檢查變量是否已定義,並採用三種不同的方法。為此,我們將使用 Spring MVC 和 Thymeleaf 構建一個簡單的 Web 應用程序,該應用程序具有一個視圖,如果設置了給定的變量,則顯示服務器的日期和時間。
2. 設置
在深入瞭解方法之前,我們需要進行一些初始設置。首先,添加以下 Thymeleaf 依賴項: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>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
現在,讓我們創建一個名為 checkVariableIsDefined 的視圖:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
th:with="lang=${#locale.language}" th:lang="${lang}">
<head>
<title>How to Check if a Variable is Defined in Thymeleaf</title>
</head>
<body>
<!-- we'll add here the relevant code for each method -->
</body>
</html>讓我們也定義兩個新的端點供此視圖使用:
@RequestMapping(value = "/variable-defined", method = RequestMethod.GET)
public String getDefinedVariables(Model model) {
DateFormat dateFormat =
DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, Locale.getDefault());
model.addAttribute("serverTime", dateFormat.format(new Date()));
return "checkVariableIsDefined.html";
}
@RequestMapping(value = "/variable-not-defined", method = RequestMethod.GET)
public String getNotDefinedVariables(Model model) {
return "checkVariableIsDefined.html";
}第一個端點加載了帶有 checkVariableIsDefined 視圖和 serverTime 變量定義的視圖,而後者則不定義該變量。
這種設置將幫助我們測試以下部分中呈現的方法。
3. 使用 #ctx 對象
我們首先要探索的方法是使用上下文對象,該對象包含 Thymeleaf 模板引擎需要處理模板的所有變量,包括對用於外部化消息的 Locale 的引用。 上下文是 IContext 接口的實現,用於獨立應用程序或 IWebContext 接口用於 Web 應用程序。
我們可以使用 #ctx 記號在 Thymeleaf 模板中訪問上下文對象。 讓我們將相關代碼添加到 checkVariableIsDefined 視圖中:
<div th:if="${#ctx.containsVariable('serverTime')}" th:text="'Server Time Using the #ctx Object Is: ' + ${serverTime}"/>現在,讓我們編寫兩個集成測試來驗證此方法:
private static final String CTX_OBJECT_MSG = "Server Time Using the #ctx Object Is: ";
@Test
public void whenVariableIsDefined_thenCtxObjectContainsVariable() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/variables-defined"))
.andExpect(status().isOk())
.andExpect(view().name("checkVariableIsDefined.html"))
.andExpect(content().string(containsString(CTX_OBJECT_MSG)));
}
@Test
public void whenVariableNotDefined_thenCtxObjectDoesNotContainVariable() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/variables-not-defined"))
.andExpect(status().isOk())
.andExpect(view().name("checkVariableIsDefined.html"))
.andExpect(content().string(not(containsString(CTX_OBJECT_MSG))));
}4. 使用 if條件語句
以下方法使用 if條件語句。讓我們更新 checkVariableIsDefined視圖:
<div th:if="${serverTime}" th:text="'Server Time Using #th:if Conditional Is: ' + ${serverTime}"/>如果變量為 null,則 if 條件語句被評估為 false。
現在,讓我們來查看一下集成測試:
private static final String IF_CONDITIONAL_MSG = "Server Time Using #th:if Conditional Is: ";
@Test
public void whenVariableIsDefined_thenIfConditionalIsTrue() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/variable-defined"))
.andExpect(status().isOk())
.andExpect(view().name("checkVariableIsDefined.html"))
.andExpect(content().string(containsString(IF_CONDITIONAL_MSG)));
}
@Test
public void whenVariableIsNotDefined_thenIfConditionalIsFalse() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/variable-not-defined"))
.andExpect(status().isOk())
.andExpect(view().name("checkVariableIsDefined.html"))
.andExpect(content().string(not(containsString(IF_CONDITIONAL_MSG))));
}如果條件語句在以下條件之一為真時被評估為 true:
- 變量是一個布爾值,其值為 true
- 變量是一個非零數字
- 變量是一個非零字符
- 變量是一個與 “false”, “off”, “no” 不同的字符串
- 變量既不是布爾值,也不是數字,也不是字符,也不是字符串
請注意,如果變量已設置,但其值為 “false”, “no”, “off”, 或 0,則 if 條件語句將被評估為 false,這可能會導致一些未預期的副作用,如果我們的意圖僅僅是檢查變量是否已設置。 讓我們通過更新視圖來説明這一點:
<div th:if='${"false"}' th:text='"Evaluating \"false\"'/>
<div th:if='${"no"}' th:text='"Evaluating \"no\"'/>
<div th:if='${"off"}' th:text='"Evaluating \"off\"'/>
<div th:if="${0}" th:text='"Evaluating 0"'/>接下來,我們創建集成測試:
@Test
public void whenVariableIsDefinedAndNotTrue_thenIfConditionalIsFalse() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/variable-defined"))
.andExpect(status().isOk())
.andExpect(view().name("checkVariableIsDefined.html"))
.andExpect(content().string(not(containsString("Evaluating \"false\""))))
.andExpect(content().string(not(containsString("Evaluating \"no\""))))
.andExpect(content().string(not(containsString("Evaluating \"off\""))))
.andExpect(content().string(not(containsString("Evaluating 0"))));
}我們可以通過檢查變量是否為 null 來解決這個問題:
<div th:if="${serverTime != null}" th:text="'Server Time Using #th:if Conditional Is: ' + ${serverTime}"/>5. 使用 unless 條件語句
最後一種方法使用 unless,它是 if 條件語句的逆否命題。 讓我們相應地更新視圖:
<div th:unless="${serverTime == null}" th:text="'Server Time Using #th:unless Conditional Is: ' + ${serverTime}"/>讓我們也測試一下這種方法是否產生預期的結果:
private static final String UNLESS_CONDITIONAL_MSG = "Server Time Using #th:unless Conditional Is: ";
@Test
public void whenVariableIsDefined_thenUnlessConditionalIsTrue() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/variable-defined"))
.andExpect(status().isOk())
.andExpect(view().name("checkVariableIsDefined.html"))
.andExpect(content().string(containsString(IF_CONDITIONAL_MSG)));
}
@Test
public void whenVariableIsNotDefined_thenUnlessConditionalIsFalse() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/variable-not-defined"))
.andExpect(status().isOk())
.andExpect(view().name("checkVariableIsDefined.html"))
.andExpect(content().string(not(containsString(UNLESS_CONDITIONAL_MSG))));
}6. 結論
在本文中,我們學習了三種用於檢查變量是否已定義的 Thymeleaf 方法。第一種方法使用 <em >#ctx</em > 對象和 <em >containsVariable</em >> 方法,而第二和最後一項方法則使用條件語句 <em >if</em >> 和其逆否條件語句 <em >unless</em >>。