Vaadin进度对话框无法在异步任务完成时接收更新并触发响应
问题原因
Vaadin 框架的所有 UI 组件属性修改操作,必须运行在对应 UI 实例绑定的 UI 线程中才会生效。你当前的ListenableFutureCallback回调逻辑是运行在 Spring @Async 注解分配的后台线程中,不属于 Vaadin 的 UI 请求线程,因此修改组件属性后,Vaadin 无法感知变更、也不会主动将更新推送到前端浏览器,所以界面没有任何变化。
解决方案
步骤1:用UI.access()包裹UI更新逻辑
在ProgressDialog构造时提前保存当前UI实例,将回调中的UI修改逻辑放到UI.access()方法中执行,确保所有操作都运行在合法的UI线程内。
修改后的ProgressDialog.java核心代码如下:
public class ProgressDialog extends Dialog { private final ListenableFuture<ResponseEntity<String>> future; // 新增:保存构造时的当前UI实例 private final UI currentUi; private ProgressBar bar; private Paragraph message; private Button close; public ProgressDialog(ListenableFuture<ResponseEntity<String>> future) { super(); this.future = future; // 构造阶段处于UI请求线程,可以直接获取当前UI this.currentUi = UI.getCurrent(); configureView(); this.future.addCallback(new ListenableFutureCallback<>() { @Override public void onSuccess(ResponseEntity<String> result) { // 将UI更新逻辑放入access方法 currentUi.access(() -> { message.setText("Task complete. Status: " + result.getStatusCode()); bar.setVisible(false); close.setEnabled(true); }); } @Override public void onFailure(Throwable ex) { currentUi.access(() -> { message.setText(ex.getMessage()); bar.setVisible(false); close.setEnabled(true); }); } }); } // 其余原有代码保持不变 private void configureView() { bar = new ProgressBar(); bar.setIndeterminate(true); bar.setVisible(true); message = new Paragraph("Executing task ..."); close = new Button("Close", this::close); close.setEnabled(false); add(bar, message, close); } private void close(ClickEvent<?> event) { this.close(); } }
步骤2:开启服务端推送
异步场景下服务端需要主动向前端推送UI更新,需要在你的路由类MainView1上添加@Push注解开启推送功能:
@Route("rescheduleWorkOrders1") @CssImport("./styles/shared-styles.css") @Push // 新增:开启服务端推送 public class MainView1 extends VerticalLayout { // 原有代码保持不变 }
内容的提问来源于stack exchange,提问作者Joseph Gagnon
相关产品推荐
相关产品推荐

