相关文章推荐
酒量小的蟠桃  ·  VBA ...·  2 年前    · 
从未表白的啄木鸟  ·  利用Traefik ...·  2 年前    · 

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 = {
		// 扫描ACommon的包,将其中的Spring组件给加载到B的Spring容器中
        "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中进行配置。