【问题标题】:When are Thymeleaf expression delimiters needed in Spring Boot?Spring Boot 什么时候需要 Thymeleaf 表达式分隔符?
【发布时间】:2021-01-26 23:30:39
【问题描述】:

我正在使用带有 Thymeleaf 的 Spring Boot 2.3.3.RELEASE。从 Thymeleaf 文档中,我不清楚何时必须在 Thymeleaf 表达式中使用 ${} 分隔符。

例如,我的模板中有这个,它正在工作:

<div th:title="${doTest() ? 'foo' : 'bar'}" />

但后来我重新阅读了文档,发现我可以使用这个:

<div th:title="${doTest()} ? 'foo' : 'bar'" />

但是? … : … 三元运算符是一个运算符,所以整个事情都是一个表达式。那么为什么我不需要${} 围绕整个属性值呢?

我也可以这样做吗?

<div th:title="doTest() ? 'foo' : 'bar'" />

这个怎么样?

<div th:title="'foo'" />

为什么是一个而不是另一个?

这个呢?我可以只使用一个裸露的true吗?

<div th:if="true">…</div>

或者我需要表达式分隔符吗?

<div th:if="${true}">…</div>

这是另一个例子:我在文档中看到了这个:

<li th:text="${item.description}" …

但是我可以只使用th:text="item.description" 吗?牙套对我有什么作用?

我也看到了:

th:each="item : ${items}"

我可以改用th:each="item : items" 吗?为什么没有 ${items} 中的大括号,Thymeleaf 不知道评估 items

当我需要${} 时,肯定有一些简单的规则,但这并不是立即显而易见的。

【问题讨论】:

    标签: spring spring-boot thymeleaf


    【解决方案1】:

    使用不带${} 的表达式将被视为(字符串、布尔值...)、操作和条件的混合,因此thymeleaf 将尝试按原样执行表达式。这是Thymeleaf 标准表达式引擎

    例如:

    th:text="item.description" :将显示item.description,如果您执行th:text="'item.description'" 则相同,因为thymeleaf 将item.description 视为文本docs

    现在将${} 与表达式一起使用,将被视为变量表达式,这意味着每个文字标记(不带''的文本)都是将在预定义的上下文中执行的变量。这是 OGNL(对象图导航语言)

    在我们的例子中:

    th:text="${item.description}":将在上下文中显示项目对象的描述。在春季,您可以使用Model(或ModelAndView)在上下文中注册您的对象:
    model.addAttribute("item", new Item()); 如果在上下文中找不到item,这将引发异常。

    所以th:text="${'item.description'}"th:text="item.description" 相同,但它们的评估方式不同。

    我认为现在很清楚,如果您想从模板中访问对象(模型、服务、存储库...),您应该使用 ${}

    【讨论】:

    • 我认为你的意思是th:text="item.description"th:text="${item.description}" 都被认为是表达式,但在前者中item.description 被认为是一个标记,而不是一个变量引用。好的,那么th:text="item.getDescription()" 呢?那会被允许吗?它会调用该方法,还是必须将其放在${…} 中?
    • 其实我不是这么说的。 ${...} 是变量表达式,“..”是非*变量表达式。所以你必须添加 ${} 才能调用该方法(应该定义'item')
    • 但是即使没有${},整个事情不是一个表达式(我没有说“变量表达式”)吗?否则,th:text="true ? 'yes' : 'no'" 将如何评估?
    • th:text="true ? 'yes' : 'no '" 它不是一个变量表达式,所以里面的所有文本要么是值(yesno')要么是 thymeleaf 理解的标记(true 是布尔值,猫王运算符... )。所以它会显示yes
    【解决方案2】:
    • 例如,我的模板中有这个,它正在工作:- 是的,因为这是由 OGNL(Object-Graph Navigation Language) 执行的
    <div th:title="{$doTest() ? 'foo' : 'bar'}" />
    
    • 但后来我重新阅读了文档,发现我可以使用这个:- 是的,因为这是由 Thymeleaf Standard Expression engine 执行的。
    <div th:title="{$doTest()} ? 'foo' : 'bar'" />
    
    • 但是? : 是一个运算符,因此整个事情都是一个表达式。那么为什么我不需要整个属性值周围的${} 呢? - 因为 thymeleaf 本身就有 Elvis Operator (?:)。所以Thymeleaf Standard Expression engine 能够执行它。

    • 这个呢?我可以只使用一个真实的吗?

      在 Thymeleaf 中,任何值都可以计算为布尔值。我们有一些价值观 解释为false:

      • 列表项

      • 布尔值 false

      • 数字0

      • 字符 \0

      • 字符串“false”、“off”和“no”

    任何其他值都被评估为true

    • 这里有一些有用的链接:-

    https://www.baeldung.com/spring-thymeleaf-conditionals

    https://www.baeldung.com/thymeleaf-boolean

    https://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf.html#variables

    http://commons.apache.org/ognl/

    编辑:-

    &lt;div th:title="{$doTest() ? 'foo' : 'bar'}" /&gt;

    &lt;div th:title="{$doTest()} ? 'foo' : 'bar'" /&gt;

    在您的情况下,您可以同时使用上述两种语法。两者的执行方式不同,但最终结果相同。第一个由 OGNL 执行,第二个由 Thymeleaf 引擎 执行。

    您的疑问是为什么第二个有效?为什么我们不需要将?: 运算符放在${} 中?

    上述问题的答案是Thymeleaf 引擎 本身就理解?: 运算符。它被称为猫王操作员。它类似于我们在大多数编程语言中使用的三元运算符,但略有不同。您可以在我分享的链接中阅读更多相关信息。

    因此,即使我们不将?: 放入${} 中,Thymeleaf Engine 也会成功执行。

    【讨论】:

    • 感谢您的回复,但核心问题是我如何分辨何时需要${},何时不需要;我觉得你的回答没有充分解决这个问题。例如,在${doTest()} 附近是否需要${}?为什么或者为什么不?我怎么知道?
    • 这就是我在上面试图解释的。没问题我会添加更多解释。
    • 但是你还没有告诉我什么时候需要花括号。我可以在没有任何花括号的情况下使用th:title="doTest() ? 'foo' : 'bar'" 吗?为什么或为什么不?
    【解决方案3】:

    如果我们需要访问变量,我们使用 ${}。变量,如您的示例 item.description,其中 item 是对象/引用,而 description 是对象 item 内的字符串。

    假设description 的值是“This is thymeleaf”。

    为了在 html 上显示描述中的文字,我们通过以下方式实现:

    <p th:text="${item.description}"></p>
    

    输出:

    这是百里香

    但不使用 ${} 表达式,将在 html 上生成给定的字符串“item.description”本身,即无法解析引用。

    <p th:text="item.description"></p>
    

    输出:

    项目描述

    我想解释另一个可能存在异常的示例,尤其是在使用 th:ifth:each 时。

    下面的两个表达式是相同的,并且会产生相同的输出:

    <p th:if="${item.description} != null"></p>
    <p th:if="${item.description != null}"></p>
    

    上面的表达式说如果item里面的description不为null就显示段落。

    Thymeleaf 希望我们使用 ${},这样如果出现这样的表达式,它就可以将大括号内的单词与其上下文中的变量进行比较,如果找到匹配项,则返回变量值。

    注意:Thymeleaf 维护一个上下文变量,可通过#ctx 访问 其中包含输入到模板的所有变量,形式为 键值对。

    如果变量没有用 ${} 括起来,那么它会将字符串视为纯文本并按原样使用它们。

    【讨论】:

      猜你喜欢
      • 2022-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-16
      • 1970-01-01
      • 2022-07-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多