我在 Tomcat 8.0.21 中声明 UI.access()

Vaadin UI.access() in Tomcat 8.0.21

当我在 Tomcat 8.0.52 中部署我的应用程序时,我有以下代码按预期工作:

button.addClickHandler(() -> {
    UI ui = UI.getCurrent();

    ui.access(() -> {
      spinner.setVisible(true);
    });
    ui.push();

    try
    {
      Thread.sleep(5000);           
    }
    catch (InterruptedException e)
    {
      LOG.error("", e)
    }  
    spinner.setVisible(false);
});

ui.access()Runnable 显示一个微调器,5 秒后微调器被隐藏。

当我在 Tomcat 8.0.21 中部署应用程序时,Runnable 未执行,因为未显示微调器。

我的 UI 被注释为 @Push(value = PushMode.MANUAL, transport = Transport.WEBSOCKET_XHR)

Push 在两个 Tomcat 版本中都工作正常,问题出在 UIaccess() 方法上。

知道为什么 ui.access() 在 Tomcat 8.0.21 中不起作用吗?

您的示例代码的编写方式不应该有效。如果它有效,那么它只是偶然起作用,因为其他事情没有按预期运行。

无论您使用哪个 Tomcat 版本,ui.push() 都会触发 运行ning 使用 ui.access() 安排的任务。您可以通过设置断点或使回调将某些内容打印到日志来确认这一点。两个 Tomat 版本之间的差异很可能与 ui.push() 直接在点击处理程序中 运行 时的其他行为有关。

ui.push() 应该在后台线程 运行 的 ui.access() 任务内部使用,以立即将任何未决更改发送到客户端。在这种情况下,该方法不是从后台线程调用的,而是从请求线程(即点击处理程序)调用的。此外,由于许多其他原因,在请求线程上休眠也是有问题的。

相反,您的代码结构应该直接将微调器设置为可见,然后安排一个线程或计时器来完成剩余的工作,最后 return 从点击处理程序急切地进行。然后线程或计时器应该使用 ui.access() 来隐藏微调器。只要您使用默认的 "automatic" 推送模式而不是 PushMode.MANUAL.

,就不需要使用 ui.push()