如果我的库也可能有带有我不知道的 Order 注释的 ControllerAdvices,我应该在 ControllerAdvice 上使用什么 order 值?

What order value do I use on a ControllerAdvice if my libraries may also have ControllerAdvices with Order annotations that I do not know about?

我有一个 Spring 4 应用程序,其中包含多个用 @Order(someValue) 注释的 ControllerAdvices。此外,我在我的一个外部库中发现了一个 ControllerAdvice,它也用 @Order(someValue) 进行了注释。

我的理解是,当 Controller 抛出异常时,ControllerAdvices 的顺序决定了在 ControllerAdvices 中搜索该特定异常的顺序。我现在认为我的外部库中也可能有其他带有 @Order 注释的 ControllerAdvices。但是,下载所有库并搜索所有 ControllerAdvices 并检查它们的 Order 值对我来说是不可行的。

如果我希望某个 ControllerAdvice 在其他 ControllerAdvice 之前捕获异常,我如何知道该将什么 Order 值放在某个 ControllerAdvice 上?我应该为我的用例使用不同的方法吗?

见下面的代码。

我希望 ExceptionHandlerControllerTwo 在 ExceptionHandlerControllerOne 之后和 ExceptionHandlerControllerThree 之前捕获异常。

我为 ExceptionHandlerControllerTwo 尝试了不同的 Order 值。数字 1 到 90 似乎以我希望的方式捕获异常。我的外部库中可能还有其他我不知道的 ControllerAdvices。

在我的应用程序中:

@ControllerAdvice
@Order(0)
public class ExceptionHandlerControllerOne {
   // multiple @ExceptionHandler methods
}
@ControllerAdvice
@Order(80)
public class ExceptionHandlerControllerTwo {
   // multiple @ExceptionHandler methods
}
@ControllerAdvice
@Order(90)
public class ExceptionHandlerControllerThree {
   // multiple @ExceptionHandler methods
}

在外部库中:

@ControllerAdvice
@Order(100)
@Slf4j
public class CatchAllExceptionHandlerController {
   // multiple @ExceptionHandler methods
}

您可以尝试查找所有 @ControllerAdvice-注释的 bean,并根据结果定义顺序。要查找订单,您可以使用以下内容:

ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
scanner.addIncludeFilter(new AnnotationTypeFilter(ControllerAdvice.class));
scanner.findCandidateComponents("org.example") // Change the package name
        .stream()
        .filter(AnnotatedBeanDefinition.class::isInstance)
        .map(AnnotatedBeanDefinition.class::cast)
        .forEach(annotatedBeanDefinition -> {
            System.out.println(
                    annotatedBeanDefinition.getBeanClassName() + ": " +
                    annotatedBeanDefinition.getMetadata().getAllAnnotationAttributes(Order.class.getName())
            );
        });

@Order(Ordered.HIGHEST_PRECEDENCE) 可以解决问题,它会告诉框架 运行 首先标记此 HIGHEST_PRECEDENCE 的建议。