【问题标题】:Scala collections support for SpringEL/ThymeleafScala 集合支持 SpringEL/Thymeleaf
【发布时间】:2013-07-05 12:25:35
【问题描述】:

我正在尝试将Thymeleaf 视图与Scala 结合使用。 我有 User 实体和一组电子邮件,我想在 Thymeleaf 模板中访问这些电子邮件:

在 User.scala 中

case class User (@BeanProperty val emails: scala.immutable.List[String])

在 some-thymeleaf-template.html 中

<div th:text="${user.emails[0]}">...</div>

问题在于 Spring 表达式求值器(Thymeleaf 将表达式求值作业委托给它)仅理解 Java 集合类型,因此尝试获取 Scala 列表 (user.emails) 的第一个元素 ([0]) 失败一个例外。

我试图深入研究 SpEL 源代码,以找到一个可以添加 Java 到 Scala 转换的地方。似乎如果我可以拦截对org.springframework.expression.PropertyAccessor.read(..) 方法的调用并在从该方法返回时执行转换,它可能会起作用。

但我找不到拦截这些电话的方法。我考虑过用代理包装这些属性访问器实例,但它们的初始化代码被硬编码到 Thymeleaf 的 SpelExpressionEvaluatorSpelVariableExpressionEvaluatorSpelEvaluationContext'classes 中,因此我没有明显的地方可以放入我的包装器。

是否有任何或多或少优雅的方式来包装 Thymeleaf 中使用的属性访问器(或者更一般地向 Thymeleaf 和/或 SpEL 添加 Scala 集合支持)而不重写过多 Thymeleaf 和 SpEL 胆量?

提前谢谢你!

【问题讨论】:

    标签: scala spring-el scala-java-interop thymeleaf


    【解决方案1】:

    您可以删除 @BeanProperty,并添加一个 getter 以实现互操作性:

    case class User(emails: List[String]) {
      def getEmails = JavaConversions.asJavaIterable(emails)
    }
    

    更优雅的是使用Scala EL resolver

    更新

    至于解析器:在 Thymeleaf/SpringEL 的某个地方,表达式解析器解析 bean 的属性:所以在您的示例中:

    ${user.emails[0]}
    

    它可能使用反射来查看user 对象中是否有getter 方法getEmails。您可以在此处添加与链接的 Scala EL 解析器中相同的代码:如果 getter 返回 Scala 集合,则将其包装在 Java 可迭代 中(或转换它到一个数组)之前。

    【讨论】:

    • 用 Java 友好的 getter 替换 @BeanProperty - 这就是我到目前为止所做的。可以作为一种解决方法,但是您关于ELResolver 的建议真的很有趣。 Spring EL 或 Thymeleaf 是否使用 ELResolver?如果是这样,我如何注册自定义解析器?
    • 是的,这就是我想要做的。有PropertyAccessor 接口,我想拦截哪个方法'read(..)'。但我只是无法找到一种方法来拦截它。通常这些访问器用'new'实例化并直接使用,所以我可能不得不重写一半的SpEL解析器才能注入我的拦截器:)但无论如何,因为看起来没有更好的选择我会最好坚持在我的案例类中添加对 Java 友好的 getter,直到 Spring 人员使 SpEL 解析器更具可扩展性。
    猜你喜欢
    • 2019-04-19
    • 1970-01-01
    • 2021-04-02
    • 2017-04-20
    • 2014-01-16
    • 2021-08-09
    • 1970-01-01
    • 2016-11-15
    • 2011-05-31
    相关资源
    最近更新 更多