Vaadin 23如何覆盖应用内部报错时的默认错误提示?
Vaadin 自定义内部错误提示的正确实现方法
现有代码的问题分析
- 错误处理器层级错误:Vaadin的错误处理优先级为「UI级 > Session级 > Service级」,仅设置Session级处理器会被UI默认处理器覆盖,无法生效。
- 异常视图状态码不匹配:当前返回
SC_NOT_FOUND(404),但内部服务器错误应对应SC_INTERNAL_SERVER_ERROR(500),状态码错误会导致系统无法正确关联错误视图。 - 通知调用逻辑冗余:
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
相关产品推荐
相关产品推荐

