【问题标题】:How to access a Spring MVC model attribute name that contain a dot in Thymeleaf如何访问在 Thymeleaf 中包含点的 Spring MVC 模型属性名称
【发布时间】:2017-01-06 16:25:49
【问题描述】:

好吧,由于 Spring Boot 框架推荐 Thymeleaf 模板引擎,所以我创建了一个简单的项目,其中使用 http://start.spring.io 选择了 WebThymeleaf 依赖项。

因为下面的HomeControllerhome/about.html 模板工作正常。

这是HomeController的java源码:

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HomeController {
    @RequestMapping("/home/about")
    public String about(Model model) {
        model.addAttribute("title", "About");
        return "home/about";
    }
}

这是home/about.html的html源代码:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <title>Test for dot!</title>
</head>
<body>
<h1 th:text="${title}">H1Title</h1>
</body>
</html>

当我更改模型属性名称时,带有一些点,例如home.about.title,完整代码如下:

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HomeController {
    @RequestMapping("/home/about")
    public String about(Model model) {
        model.addAttribute("home.about.title", "About");
        return "home/about";
    }
}

而html代码变成这样:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <title>Test for dot!</title>
</head>
<body>
<h1 th:text="${home.about.title}">H1Title</h1>
</body>
</html>

嗯,发生了一些错误,这令人困惑!

那么,模型属性名称中的 dot 是怎么回事?它是保留使用的特殊字符吗?以及如何让它发挥作用?

我在 StackOverflow 中搜索并找到了一个类似的问题 How to access a Spring MVC model attribute name that contain a dot in Freemarker?,但该问题的答案不适用于 Thymeleaf。

【问题讨论】:

  • 不是这方面的专家,但我认为 thymeleaf 正在寻找带有“about”字段的属性“home”,它本身带有一个子字段“title”。好像你已经完成了model.addAttribute("home", new Home(new About("title")));
  • @alexbt 好吧,我也有同样的想法,但我找不到任何官方文档指定该限制或模糊用法。实际上,我什至不知道home.about.title 是否是文本区分的最佳实践。
  • 当你在属性名称中使用点时,你使用的是一个关键字符,那么在你看来,thymeleaf 认为对象“home”有一个名为“about”的属性,这也有一个 final 属性称为“标题”,这是不正确的,这就是失败的原因。有同事说,用i18国际化

标签: spring spring-mvc spring-boot thymeleaf


【解决方案1】:

点用于指代对象的属性/方法。当您有表达式${home.about.title} 时,它会尝试查找模型对象home 并调用home.getAbout().getTitle()。我已经能够通过做这样的事情来解决这个问题

<!-- thymeleaf 2 -->
<span th:text="${#vars.get('home.about.title')}" />

<!-- thymeleaf 3 -->
<span th:text="${#vars.getVariable('home.about.title')}" />

但我不会推荐它。你真的应该远离在模型属性中使用点字符。

【讨论】:

    【解决方案2】:

    处理这样的国际化消息不是一个好习惯。

    对于 Spring Boot 项目,在 src/main/resources/

    中创建文件 messages.properties(messages_cs.properties 等)

    src/main/resources/messages.properties的内容为

    home.about.title=About
    

    然后在 Thymeleaf 中,您将使用标签而不是美元。

    <h1 th:text="#{home.about.title}">H1Title</h1>
    

    【讨论】:

    • 嗯,感谢您的回答,但是,您可能会错过重点。问题与国际化消息无关,我只想知道如何访问模型属性名称在 Thymeleaf 中包含一个点。
    • 好吧,我不认为这是可能的,因为它会与对象实例上的调用方法发生冲突。
    【解决方案3】:

    如果这些不仅仅是需要国际化的“消息”,或者您不能遵循标准约定,我认为最好的方法是创建一个包含您想要的属性的类。例如,Properties 类是内置的(我相信从 JDK 7 开始)。

    在您的控制器中:

    Properties props = new Properties();
    props.setProperty("my.key", "my.value");
    model.add(props, "Properties");
    

    然后,在您的模板中:

    <span th:text="${Properties.getProperty('my.key')}" />
    

    当然,您可以创建自己的包装类并更改方法名称以使访问更方便,因此最终结果可能更像:

    <span th:text="${Store.get('my.key')}" />
    

    【讨论】:

      【解决方案4】:

      如果您请求的属性名称带有点,您可以通过隐式 HttpServletRequest 对象访问它。例如:

      ${#request.getAttribute('javax.servlet.error.exception')}
      

      【讨论】:

        猜你喜欢
        • 2013-08-27
        • 2022-12-24
        • 1970-01-01
        • 2020-08-02
        • 2019-05-17
        • 1970-01-01
        • 1970-01-01
        • 2011-06-19
        • 1970-01-01
        相关资源
        最近更新 更多