spring 解决Thymeleaf中缺少可选支持的问题

mzmfm0qo  于 2022-11-21  发布在  Spring
关注(0)|答案(3)|浏览(164)

现在是2020年,Thymeleaf仍然是六年前发布的Java8的doesn't support Optional。有什么解决办法吗?
我正在使用Sping Boot 2.3.3.RELEASE和Thymeleaf。我有一个Foo类型的对象,控制器通过模型/会话提供foo。它有一个返回Optional<String>的方法findName()。所以我可以把它放在我的模板中:

[[${foo.findName()}]]

假设名称为"bar",则显示:
Optional[bar]
那很好,但显然不是我想要的。
所以我尝试了Java中的方法。下面的代码应该只打印名称(例如foo),如果名称缺失,则打印_____

[[${foo.findName().orElse("_____")}]]

不幸的是,这会产生一个例外:
org.thymeleaf.exceptions.TemplateProcessingException: Could not parse as expression: ""
尝试使用条件,这将提供值(如果存在):

[[${foo.findName().isPresent()} ? ${foo.findName().get()}]]

但由于某种原因,这会抛出一个异常:

[[${foo.findName().isPresent()} ? ${foo.findName().get()} : '_____']]

首先,我不知道为什么使用orElse()的示例不起作用,因为Optional示例和其他示例一样是一个对象。其次,有人知道一个解决方案吗?第三,有人知道一个简洁的解决方案,不会占用三倍的代码吗?
(What我们真正需要的是Thymeleaf中的原生支持,这样${foo.findName()} ?: '_____'才能正常工作。)

31moq8wy

31moq8wy1#

由于Thymeleaf在与Spring集成时使用了Spring Expression语言,因此Thymeleaf并不应受到指责。截至目前的Spring版本,SpEl还不支持Java 8 Optional,这是GitHub的问题#20433
可能的解决方法需要不同的表达式:

  • 当您有预设值时(_逸出问题已透过注解解决)
<span th:text="${foo.findName().orElse('---')" />
  • 如果不想呈现enpty(或default)行,可以使用th:if隐藏它:
<th:block th:if="${foo.findName().isPresent()}">
    <span th:text="${foo.findName().get()" /> 
</th:block>`
63lcw9qa

63lcw9qa2#

到目前为止,我唯一能做的就是:

<th:block th:switch="${foo.findName().isPresent()}">
  <th:block th:case="true">[[${foo.findName.get()}]]</th:block>
  <th:block th:case="*">_____</th:block>
</th:block>

恐怖--如此冗长!这是最好的办法吗?

eoigrqb6

eoigrqb63#

作为Java Optionals功能的解决方法,使用SpringEL的“Elvis运算符”和“安全导航运算符”:

安全导航操作员:如果myOptional为null,则将返回null而不是错误:

myOptional.orElse(null)?.myProperty

这在Java中相当于:

myOptional.map(ObjectType::getMyProperty).orElse(null);

猫王接线员如果myOptional或myProperty为空,则返回“alternativeContent”:

myOptional.orElse(null)?.myProperty?:"alternativeContent"

这在Java中相当于:

myOptional.map(ObjectType::getMyProperty).orElse("alternativeContent");

更简单的方法可能是,不要将Optional全部传递给Thymeleaf,而只使用上面提到的运算符

myObject?.myProperty
myObject?.myProperty?:"alternativeContent"

相关问题