【问题标题】:Webflux Reactive objects not resolved before rendering Thymeleaf View在渲染 Thymeleaf 视图之前未解析 Webflux Reactive 对象
【发布时间】:2020-08-11 16:13:48
【问题描述】:

当我尝试在 Thymeleaf 中呈现我的视图时,我收到错误 Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'currentTemperature' cannot be found on object of type 'reactor.core.publisher.MonoMapFuseable' - maybe not public or not valid?

Spring WebFlux 文档指出“具有反应式类型包装器的模型属性被解析为其实际值”,但是将 Mono 作为模型传递给视图会给我上述错误。

  @RequestMapping(path = "/")
  @GetMapping
  public String home(Model model) {
    Mono<ThermostatState> thermostatState = thermostatClient.fetchThermostatState();
    model.addAttribute("thermostatState", thermostatState);
    return "home";
  }

阻塞 Mono 并解开内部值使模板呈现不变,但有点消除了使用响应式库的意义。

  @RequestMapping(path = "/")
  @GetMapping
  public String home(Model model) {
    Mono<ThermostatState> thermostatState = thermostatClient.fetchThermostatState();
    ThermostatState unwrappedState = thermostatState.block();
    model.addAttribute("thermostatState", unwrappedState);
    return "home";
  }

项目完全依赖spring starter依赖,没有显式的配置类。

【问题讨论】:

    标签: java thymeleaf spring-webflux


    【解决方案1】:

    您好,我也是 Spring 和响应式编程的新手;但我认为,可以这样处理。

     @RequestMapping(path = "/")
     @GetMapping
     public Mono<String> home(Model model) {
        return thermostatClient.fetchThermostatState()
          .map(thermostatState -> {
             model.addAttribute("thermostatState", thermostatState);
             return "home";
          });
     }
    

    【讨论】:

    • 您的代码有效,我认为它比使用block() 更好。我想你的方式不会占用我的方式(不确定这是否属实,但这是有道理的)。但是我觉得没有必要将控制器的返回推迟到未来解决。 Thymeleaf Webflux 示例不这样做 github.com/thymeleaf/thymeleafsandbox-biglist-reactive/blob/… 但由于某种原因它对我不起作用。
    • 顺便说一句,方法的返回值需要从String更改为Mono&lt;String&gt; ,以上代码才能正常工作。
    • 是的,我错过了更改返回类型,我更正了它。很高兴看到我的回答对你有帮助。请将其标记为答案,如果它对您来说是正确的解决方案,
    • 如果它对你有用,那么你应该接受这个答案@JoshRivers
    • @Shoshi 请注意代码“有效”(就像我的示例中使用 block() 的代码一样,但我的问题没有解决,因为框架仍然没有按记录或预期工作. Krishna 的回答是一个优雅的解决方法,但可能会产生性能副作用(不清楚是否是这种情况),并且它仍然不能使模板/模型解析器原生地与反应对象一起工作。如果在模板呈现之前,需要收集和解决多个未来。
    【解决方案2】:

    我能够通过从我的 pom.xml 中删除以下内容来解决此问题

        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
    

    这是由 Spring starter 毫无怨言地添加的,但它与 Webflux 准不兼容。该应用程序运行时没有任何抱怨,但是当它在启动日志中报告它是从 Tomcat 启动而不是 Netty 时,您可以说是出了点问题。这表明它作为旧式 MVC 应用程序运行,而不是 Webflux 应用程序。发现这一点后,我能够找到另一个问题的解释性答案:https://stackoverflow.com/a/48418409/23276(不同的症状,但相同的答案)。这里还有一点解释:https://stackoverflow.com/a/51378560/23276

    我能够通过创建一个单依赖示例应用程序来证明事情最初是可行的,该应用程序的工作方式符合我在文档中所期望和看到的方式。然后我尝试一一删除不同的依赖,直到发现冲突为止。

    在解决这个问题时,我的 IDE 会做一些奇怪的事情来缓存依赖项,这阻碍了我。当我进入命令行并尝试使用 mvn cleanmvn spring-boot:run 直到找到损坏的依赖项时,发现问题变得更容易了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-25
      • 2016-04-16
      • 1970-01-01
      • 2014-11-04
      • 1970-01-01
      • 2018-11-27
      • 1970-01-01
      相关资源
      最近更新 更多