首页 > 解决方案 > 在方法执行之前加载 Thymeleaf 片段

问题描述

我有一个这样的控制器:

@Controller
public class DeviceController {

  @Inject
  private DeviceService deviceService;

  @ModelAttribute("devices")
  public List<Device> getDevices() {
    return deviceService.getAll();
  }

  @GetMapping({"/", "index.html"})
  public String showIndex() {
    return "index";
  }

  @DeleteMapping(value = "/devices/{id}")
  public String deleteOne(@PathVariable("id") long id) {
    deviceService.deleteOne(id);
    return "index :: devices";
  }
}

还有一个像这样的 Thymeleaf 模板:

<table id="tbl_device" th:fragment="devices">
  <tr> <!-- header --> </tr>
  <tr th:each="e : ${devices}" th:object="${d}" th:id="'device_' + *{id}" th:fragment="'device_' + *{id}">
    <!-- columns -->
  </tr>
</table>

当我调用/devices/{id}DELETE 端点时,我希望它返回没有删除设备的表。但它实际上返回了包含已删除设备的表。当我调试代码时,我可以看到它getDevices()被调用 before deleteOne(id)

当我在删除后手动重新加载页面时,该行(正确)不再显示。

这是为什么?并且(如何)我可以改变这种行为?
谢谢

标签: javaspring-bootthymeleaf

解决方案


这是为什么?

我推荐阅读这篇文章。据此:

一般来说,Spring-MVC 总是先调用该方法,然后再调用任何请求处理程序方法。也就是说,@ModelAttribute 方法在调用带有 @RequestMapping 注释的控制器方法之前被调用。序列背后的逻辑是,模型对象必须在控制器方法内部开始任何处理之前创建。

我怀疑你可以改变调用顺序,但你可以做的是另外将模型属性传递给你的deleteOne方法并在那里修改它。

@DeleteMapping(value = "/devices/{id}")
public String deleteOne(@PathVariable("id") long id, @ModelAttribute("devices") List<Device> devices) {
    deviceService.deleteOne(id);
    devices.remove( /* just deleted device */);
    return "index :: devices";
}

推荐阅读