Thymeleaf中检查是否定义了变量的三种方法

在本教程中,我们将学习如何使用三种不同的方法检查Thymeleaf中是否定义了变量。为此,我们将使用Spring MVC 和 Thymeleaf构建一个简单的 Web 应用程序,该应用程序具有单个视图,如果设置了给定变量,该视图将显示服务器日期和时间。

设置
在深入研究这些方法之前,我们需要进行一些初始设置。让我们从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";
}

第一个端点加载已定义serverTime变量的checkVariableIsDefined视图,而后一个端点加载未定义变量的相同视图。

此设置将帮助我们测试以下部分中介绍的方法。

使用ctx对象
我们将探索的第一个方法使用 context 对象,它包含 Thymeleaf 模板引擎处理模板所需的所有变量,包括对用于外部化消息的Locale的引用。上下文是独立应用程序的IContext接口或 Web 应用程序的IWebContext接口的实现。

我们可以使用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))));
}

使用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))));
}

如果以下任一条件为真,则if条件被评估为真:
  • 该变量是一个布尔值,值为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"))));
}

我们可以通过检查变量不为空来解决这个问题:

<div th:if="${serverTime != null}" th:text="'Server Time Using th:if Conditional Is: ' + ${serverTime}"/>

使用unless条件
最后一个方法使用except,它是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))));
}

结论
在本文中,我们学习了三种检查 Thymeleaf 中是否定义变量的方法。第一个方法使用ctx对象和containsVariable方法,而第二个和最后一个方法使用条件语句if及其相反的except。