2个服务:A-common 和 BService,各自有异常处理器。
其中A中定义了通用的异常处理器,供所有服务直接调用。
但是B服务由于业务需求需要处理一些A中没有的异常,由于A中存在兜底逻辑:对Exception进行捕获,这个时候就要指定异常处理器的执行顺序。
Spring的异常处理器是根据异常处理器被加载的顺序来顺序执行,比如:A->B->C ,如果B拦截并且处理了某个异常,就会直接抛出,C的异常处理器就执行不到了。
可以通过 @Order 注解来指定实体Bean被加载到Spring容器的顺序,注解中的值越小越优先加载。多个自定义的ExceptionHandler类的执行顺序就是被Spring加载到容器中Bean加载顺序,ExceptionHandlerMethodResolver根据order值进行执行。
原理:
https://juejin.cn/post/6844903865054150669
B的启动类
@Slf4j
@EnableSwagger2
@RegisterHttpService
@SpringBootApplication(scanBasePackages = {"com.bytedance.cg.gcrm","com.bytedance.cg.mtm.tenant.sdk"})
@MapperScan(basePackages = {
"com.Acommon.infrastructure",
"com.BService",
@EnableAsync
public class Application {
public static void main(String[] args) {
TimeZone.setDefault(TimeZone.getTimeZone("GMT+0"));
ConvertPatternLayout.init();
log.info("start spring...");
SpringApplication.run(Application.class, args);
指定B的ExceptionHandler为第一执行顺序
@ControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
public class GlobalExceptionHandlerFirst {
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandlerFirst.class);
@ExceptionHandler({ThriftInvokeException.class})
@ResponseBody
public Response handleThriftInvokeException(ThriftInvokeException e) {
log.error("handle ThriftInvokeException. message:{}", new Object[]{e.getMessage()});
……dosth
@Order的源码以及使用范例:https://blog.csdn.net/yaomingyang/article/details/86649072
1, 注解@Order或者接口Ordered的作用是定义Spring IOC容器中Bean的执行顺序的优先级,而不是定义Bean的加载顺序,Bean的加载顺序不受@Order或Ordered接口的影响
2, 加载代码的底层要支持优先级执行程序,否则即使配置上Ordered、@Order也是不起任何作用的
ExceptionHandlerMethodResolver调用链:https://juejin.cn/post/6844903865054150669
文章目录背景解决方案代码背景2个服务:A-common 和 BService,各自有异常处理器。其中A中定义了通用的异常处理器,供所有服务直接调用。但是B服务由于业务需求需要处理一些A中没有的异常,由于A中存在兜底逻辑:对Exception进行捕获,这个时候就要指定异常处理器的执行顺序。解决方案Spring的异常处理器是根据异常处理器被加载的顺序来顺序执行,比如:A->B->C ,如果B拦截并且处理了某个异常,就会直接抛出,C的异常处理器就执行不到了。可以通过 @Order 注解来
在springboot多模块中, common模块有全局异常处理, A模块引用了common模块, 且A模块中有自己的全局异常处理, 在有些服务中是A中的全局异常处理生效, 有些服务中是common模块中的全局异常处理生效. 非常疑惑, 了解后写下此篇.
先加载的@ControllerAdvice类里如果存在@ExceptionHandler(xxException.class)是需要捕获的异常或其父类,则将使用先加载的类中的异常处理方式。如果没有,则看后面的@ControllerAd
1.先看异常是不是@ExceptionHandler中配置的
2.异常可能提示的是A异常,实际上捕捉的B异常,例如JsonParseExcepetion被捕捉,抛出的是HttpMessageNotReadableException异常
源码解析:
AbstractHandlerExceptionResolver中调用resolveException方法
public ModelAndView resolveException(HttpServletRequest request, HttpServl
拦截器接口
public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
@ExceptionHandler(value = BusinessException.class)
@ResponseBody
public ResultVO handlerSellerException(BusinessException e) {
return ResultVOUtil.error(e.getException...
直接在Controller里面加上用@ExceptionHandler标注一个处理异常的方法像下面这样子
@ExceptionHandler(MissingServletRequestParameterException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
Spring MVC的HandlerInterceptor和ExceptionHandler是两个拦截器,它们的执行机制如下:
1. HandlerInterceptor的执行机制:
在请求到达Handler之前,会先经过HandlerInterceptor的preHandle方法。如果该方法返回true,说明请求可以继续执行,否则请求将被拦截,不会到达Handler。
在请求处理完成后,会经过HandlerInterceptor的postHandle方法,该方法可以对请求的结果进行处理。
最后,在请求结束后,会经过HandlerInterceptor的afterCompletion方法,该方法可以对请求进行一些清理操作。
2. ExceptionHandler的执行机制:
当请求处理过程中发生异常时,会先经过ExceptionHandler的resolveException方法,该方法可以对异常进行处理。
如果resolveException方法返回null,说明该异常还没有被处理,那么会按照异常的类型进行查找对应的ExceptionHandler,如果找到了对应的ExceptionHandler,就会执行该ExceptionHandler的resolveException方法,如果没有找到对应的ExceptionHandler,则会按照默认的处理方式进行处理。
需要注意的是,ExceptionHandler的resolveException方法只能处理Controller中抛出的异常,对于其他的异常,比如404、500等,需要在web.xml中进行配置。