Spring应用中如何让自定义异常处理器优先于Sentry执行?
这个问题的核心是HandlerExceptionResolver的执行顺序:Sentry注册的SentryExceptionResolver和Spring处理@ControllerAdvice的ExceptionHandlerExceptionResolver会竞争处理异常,默认情况下Sentry的Resolver可能先执行,导致你的自定义处理器没机会工作。下面是两种靠谱的解决办法:
方法一:调整Sentry异常解析器的执行顺序
Spring中HandlerExceptionResolver的执行优先级由order值决定——order值越小,优先级越高。默认情况下,处理@ControllerAdvice的ExceptionHandlerExceptionResolver的order是0,所以我们只需要给SentryExceptionResolver设置一个更大的order值,让自定义处理器先执行即可。
修改你的Sentry配置类:
@Configuration public class FactoryBeanAppConfig { @Bean public HandlerExceptionResolver sentryExceptionResolver() { SentryExceptionResolver resolver = new SentryExceptionResolver(); // 设置比默认ExceptionHandlerExceptionResolver更高的order,确保自定义处理器先执行 resolver.setOrder(100); return resolver; } @Bean public ServletContextInitializer sentryServletContextInitializer() { return new SentryServletContextInitializer(); } }
这样一来,你的@ControllerAdvice异常处理器会先捕获并处理MethodArgumentNotValidException、NotFoundException等异常,只有那些没被自定义处理器处理的异常,才会被Sentry捕获上报。
方法二:自定义Sentry异常解析器,过滤已处理的异常
如果你想更精准地控制哪些异常需要上报Sentry,可以重写SentryExceptionResolver的resolveException方法,直接过滤掉你已经处理过的异常类型,或者判断响应是否已经被提交(说明自定义处理器已经处理过了)。
示例代码:
@Configuration public class FactoryBeanAppConfig { @Bean public HandlerExceptionResolver sentryExceptionResolver() { return new SentryExceptionResolver() { @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { // 1. 如果响应已经被提交,说明自定义处理器已经处理完成,直接返回null跳过Sentry上报 if (response.isCommitted()) { return null; } // 2. 直接过滤掉你已经处理过的异常类型 if (ex instanceof MethodArgumentNotValidException || ex instanceof NotFoundException || ex instanceof BadRequestException) { return null; } // 其他未处理的异常,交给Sentry处理 return super.resolveException(request, response, handler, ex); } }; } @Bean public ServletContextInitializer sentryServletContextInitializer() { return new SentryServletContextInitializer(); } }
这种方式的优势是灵活性更高,你可以根据业务需求动态调整需要上报的异常范围。
内容的提问来源于stack exchange,提问作者Pablo Fernandez

