You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vaadin 23如何覆盖应用内部报错时的默认错误提示?

Vaadin 自定义内部错误提示的正确实现方法

现有代码的问题分析

  1. 错误处理器层级错误:Vaadin的错误处理优先级为「UI级 > Session级 > Service级」,仅设置Session级处理器会被UI默认处理器覆盖,无法生效。
  2. 异常视图状态码不匹配:当前返回SC_NOT_FOUND(404),但内部服务器错误应对应SC_INTERNAL_SERVER_ERROR(500),状态码错误会导致系统无法正确关联错误视图。
  3. 通知调用逻辑冗余:ErrorHandler中重复调用Notification.show,且未完全保证UI线程安全。

修正后的代码实现

1. 自定义错误处理器(处理UI异步错误)

public class CustomErrorHandler implements ErrorHandler {
    private static final Logger logger = LoggerFactory.getLogger(CustomErrorHandler.class);

    @Override
    public void error(ErrorEvent errorEvent) {
        Throwable throwable = errorEvent.getThrowable();
        logger.error("内部错误发生", throwable);

        // 确保在UI线程安全的环境下显示通知
        UI ui = UI.getCurrent();
        if (ui != null) {
            ui.access(() -> {
                Notification.show(
                    "抱歉,系统发生内部错误,请联系技术支持。",
                    5000,
                    Notification.Position.BOTTOM_CENTER
                );
            });
        }
    }
}

2. 服务初始化监听器(设置UI级错误处理器)

@Component
public class ServiceListener implements VaadinServiceInitListener {
    private static final Logger logger = LoggerFactory.getLogger(ServiceListener.class);

    @Override
    public void serviceInit(ServiceInitEvent event) {
        event.getSource().addSessionInitListener(
            initEvent -> logger.info("新会话已初始化!")
        );

        event.getSource().addUIInitListener(initEvent -> {
            logger.info("新UI已初始化!");
            // 在UI级别设置错误处理器,确保覆盖默认逻辑
            initEvent.getUI().setErrorHandler(new CustomErrorHandler());
        });
    }
}

3. 路由异常处理视图(处理路由过程中的异常)

@ParentLayout(MainLayout.class)
@AnonymousAllowed
public class InternalErrorView extends VerticalLayout implements HasErrorParameter<Exception> {
    static final Logger logger = LoggerFactory.getLogger(InternalErrorView.class);

    @Override
    public int setErrorParameter(BeforeEnterEvent event, ErrorParameter<Exception> parameter) {
        Exception exception = parameter.getException();
        logger.error("路由错误发生", exception);

        // 布局调整,让错误提示居中显示
        setSizeFull();
        setAlignItems(Alignment.CENTER);
        setJustifyContentMode(JustifyContentMode.CENTER);

        add(new H1("系统内部错误"));
        add(new Paragraph("抱歉,系统暂时无法处理您的请求,请稍后重试或联系技术支持。"));

        // 返回正确的HTTP内部服务器错误状态码
        return HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
    }
}

关键注意事项

  • 覆盖所有错误场景:ErrorHandler处理UI组件事件等异步错误,HasErrorParameter视图处理路由过程中的异常,两者配合才能完全替换默认错误提示。
  • 线程安全:所有UI更新操作必须通过UI.access()执行,避免非UI线程操作导致的异常。
  • 状态码匹配:确保返回的HTTP状态码与错误类型对应,内部错误必须使用500,否则系统不会正确映射到自定义视图。

内容的提问来源于stack exchange,提问作者alexanoid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 07:24:25