当前位置: 首页 > 知识库问答 >
问题:

设置多个@控件建议@ExceptionHandler的优先级

红砚文
2023-03-14

我有多个用ControllerAdvice注释的类,每个类在中都有一个ExceptionHandler方法

处理异常的意图是,如果找不到更具体的处理程序,就应该使用它。

可悲的是,Spring MVC似乎总是使用最通用的情况(Exception)而不是更具体的情况(IOException例如)。

这就是人们期望Spring MVC的表现吗?我试图模拟Jersey的一个模式,该模式评估每个异常映射(等效组件),以确定它处理的声明类型与抛出的异常之间的距离,并始终使用最近的祖先。

共有3个答案

徐智渊
2023-03-14

可以使用order注释更改异常处理程序的顺序。

例如:

import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.web.bind.annotation.ControllerAdvice;

@ControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CustomExceptionHandler {

    //...

}

@order的值可以是任何整数。

施永贞
2023-03-14

在进一步的调查中,我们发现,无论如何,在Spring 3.2.4中,查找@ControlllerAdVP注释的代码还会检查@order注释的存在并对ControlllerAdviceBeans的列表进行排序。

没有@order注释的所有控制器的结果默认顺序是有序#LOWEST_PRECEDENCE这意味着如果您有一个控制器需要最低优先级,那么您的所有控制器都需要更高的顺序。

下面的示例显示了如何拥有两个异常处理程序类,这些类带有ControllerAdvice和Order注释,可以在发生UserProfileException或RuntimeException时提供适当的响应。

class UserProfileException extends RuntimeException {
}

@ControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
class UserProfileExceptionHandler {
    @ExceptionHandler(UserProfileException)
    @ResponseBody
    ResponseEntity<ErrorResponse> handleUserProfileException() {
        ....
    }
}

@ControllerAdvice
@Order(Ordered.LOWEST_PRECEDENCE)
class DefaultExceptionHandler {

    @ExceptionHandler(RuntimeException)
    @ResponseBody
    ResponseEntity<ErrorResponse> handleRuntimeException() {
        ....
    }
}
  • 请参阅ControllerAdvicean#initOrderFromBeanType()
  • 请参阅ControllerAdviceean#findAnnotatedBeans()
  • 请参阅ExceptionHandlerExceptionResolver#initExceptionHandlerAdviceCache()

享受吧!

叶阳
2023-03-14

这就是人们期望Spring MVC的表现吗?

从Spring 4.3.7开始,Spring MVC的行为如下:它使用HandlerExceptionResolver实例来处理处理程序方法引发的异常。

默认情况下,web MVC配置注册单个HandlerExceptionResolver bean,即HandlerExceptionResolverComposite

委托到其他句柄异常解析器列表。

其他解析器是

  1. 异常处理程序异常解析器
  2. 响应状态异常解析器
  3. 默认处理程序异常解析器

按该顺序注册。就这个问题而言,我们只关心异常句柄异常解析器(ExceptionHandlerExceptionResolver)。

一种通过ExceptionHandler方法解析异常的AbstractHandlerMethodExceptionResolver。

在上下文初始化时,Spring将为它检测到的每个带注释的类生成一个ControlllerAdviceBeanExceptionHandlerExceptionResolver将从上下文中检索这些,并使用AnnotationAware OrderCompator对它们进行排序

是OrderComparator的扩展,支持Spring的Ordered接口以及Order和Priority注释,其中Ordered实例提供的Order值覆盖静态定义的注释值(如果有)。

然后,它将为这些ControllerAdviceean实例中的每个实例注册一个ExceptionHandlerMethodResolver(将可用的ExceptionHandler方法映射到它们要处理的异常类型)。它们最终以相同的顺序添加到LinkedHashMap(保留迭代顺序)。

发生异常时,ExceptionHandlerExceptionResolver将遍历这些异常HandlerMethodResolver,并使用第一个可以处理异常的异常。

所以这里的重点是:如果您有一个带有@ExceptionHandlerforException@ExceptionHandler,它在另一个@ControlllerAdvie类之前注册,该类带有@ExceptionHandler用于更具体的异常,例如IOException,第一个将被调用。如前所述,您可以通过让您的@ControlllerAdvie带注释的类实现有序的或使用@order@优先级对其进行注释并为其提供适当的值来控制注册顺序。

 类似资料:
  • 问题内容: 我有一个在几个线程中运行的程序。主线程与其他线程共享一个对象,在主线程中,我需要调用: 我怀疑主线程饿了,无法访问。如何提高主线程的优先级,或者默认情况下它是否已高于其他线程? 问题答案: 您在Thread类中有一个setPriority()方法。 检查此javadoc。 将线程优先级设置为最大:

  • 问题内容: 在似乎缺少该FEATURE:一种方式保存文件(通常被选中,这样,当用户开始输入将被替换的东西)时,建议的文件名。 有没有解决的办法? 问题答案: 如果我对您的理解正确,则需要使用该方法。 该文件不需要存在。 编辑: 如果您传递带有绝对路径的文件,将尝试将其自身放置在该目录中(如果存在)。

  • AL01299205:Hadoop用户$/usr/local/cellar/hadoop/3.2.1/sbin/start-dfs.sh 正在启动[AL01299205.Local]上的namenodes AL01299205.Local:错误:无法设置namenode进程24897的优先级

  • 根据用户的使用习惯从费用和安全两方面提供优化建议,达到费用优化,提高安全性的目的。 成本优化 通过系统内置规则,将匹配规则的闲置浪费或安全性较低的资源扫描出来并按照建议进行处理,从而达到节约成本、提高资源安全性的目的。 安全检查 通过系统内置规则,将匹配规则的安全性较低的资源扫描出来并按照建议进行处理,从而提高系统安全性的目的。

  • 架构及开发过程优化建议: 路由尽量使用域名路由或者路由分组; 在路由中进行验证和权限判断; 合理规划数据表字段类型及索引; 结合业务逻辑使用数据缓存,减少数据库压力; 在应用完成部署之后,建议对应用进行相关优化,包括: 如果开发过程中开启了调试模式的话,关闭调试模式(参考调试模式); 通过命令行生成类库映射文件; 通过命令行生成配置缓存文件; 生成数据表字段缓存文件;

  • 我有两个SQS队列:一个用于低优先级,另一个用于高优先级消息。逻辑是不要接触低优先级队列上的消息,除非高优先级队列为空。 现在,我将这两条路由设置为同时使用队列中的消息。我想要的是,一个消息进入高优先级路由触发低优先级路由的停止。为了尝试获得此功能,我尝试使用一种路由策略,当在高优先级路由上启动新交换时,该策略将停止低优先级队列: (来自的片段) 然而,我不确定如何重新启动低优先级的消费者。骆驼提