Eng*_*_DJ 68 exception-handling spring-mvc
我有多个用类注释的类@ControllerAdvice,每个类都带有一个@ExceptionHandler方法.
一个处理Exception的目的是如果找不到更具体的处理程序,则应该使用它.
可悲的是,Spring MVC似乎总是使用最通用的case(Exception)而不是更具体的case(IOException例如).
这是人们期望Spring MVC的表现吗?我正在尝试模拟来自Jersey的模式,它评估每个ExceptionMapper(等效组件)以确定它处理的声明类型与已抛出的异常的距离,并始终使用最近的祖先.
Sot*_*lis 104
这是人们期望Spring MVC的表现吗?
从Spring 4.3.7开始,这里是Spring MVC的行为:它使用HandlerExceptionResolver实例来处理由处理程序方法抛出的异常.
默认情况下,Web MVC配置注册一个HandlerExceptionResolverbean HandlerExceptionResolverComposite,即
委托给其他人的名单
HandlerExceptionResolvers.
那些其他的解析器是
ExceptionHandlerExceptionResolverResponseStatusExceptionResolverDefaultHandlerExceptionResolver在那个顺序登记.出于这个问题的目的,我们只关心ExceptionHandlerExceptionResolver.
一
AbstractHandlerMethodExceptionResolver,通过解析异常@ExceptionHandler的方法.
在上下文初始化时,Spring将为它检测到的ControllerAdviceBean每个带@ControllerAdvice注释的类生成一个.该ExceptionHandlerExceptionResolver会从上下文检索这些,并使用排序,使用AnnotationAwareOrderComparator其
是的扩展
OrderComparator支持Spring的Ordered界面,以及在@Order和@Priority注解,与由有序实例覆盖静态定义的注释值(如果有的话)提供的命令值.
然后,它将ExceptionHandlerMethodResolver为每个ControllerAdviceBean实例注册一个(将可用@ExceptionHandler方法映射到它们要处理的异常类型).这些最终以相同的顺序添加到LinkedHashMap(保留迭代顺序).
当发生异常时,ExceptionHandlerExceptionResolver将遍历这些ExceptionHandlerMethodResolver并使用可以处理异常的第一个异常.
因此,这里的一点是:如果你有一个@ControllerAdvice带有@ExceptionHandler用于Exception该被另一注册前@ControllerAdvice与类@ExceptionHandler的更具体的例外,比如IOException,是第一个将被调用.正如前面提到的,你可以有你的控制是为了注册@ControllerAdvice注解类实现Ordered或注释它@Order或者@Priority,给它一个合适的值.
Dom*_*ton 82
Sotirios Delimanolis对他的回答非常有帮助,经过进一步的调查,我们发现,在3.2.4版本中,查找@ControllerAdvice注释的代码也会检查@Order注释的存在并对ControllerAdviceBeans列表进行排序.
没有@Order注释的所有控制器的最终默认顺序是Ordered#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() {
....
}
}
Run Code Online (Sandbox Code Playgroud)
请享用!
Kor*_*tor 19
可以使用@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 {
//...
}
Run Code Online (Sandbox Code Playgroud)
@Order的值可以是任何整数.
小智 6
我还在文档中发现:
异常处理方法
受保护的 ServletInvocableHandlerMethod getExceptionHandlerMethod(HandlerMethod handlerMethod, Exception 异常)
查找给定异常的 @ExceptionHandler 方法。默认实现首先在控制器的类层次结构中搜索方法,如果没有找到,它会继续搜索其他 @ExceptionHandler 方法,假设检测到一些 @ControllerAdvice Spring 管理的 bean。参数: handlerMethod - 引发异常的方法(可能为 null) exception - 引发的异常返回:处理异常的方法,或 null
所以这意味着如果你想解决这个问题,你需要在抛出这些异常的控制器中添加你的特定异常处理程序。并定义一个且唯一的 ControllerAdvice 处理全局默认异常处理程序。
这简化了过程,我们不需要 Order 注释来处理问题。
您还可以使用数值,如下所示
@Order(value = 100)
Run Code Online (Sandbox Code Playgroud)
较低的值具有较高的优先级。默认值是 * {@code Ordered.LOWEST_PRECEDENCE},表示最低优先级(输给任何其他指定的顺序值)
| 归档时间: |
|
| 查看次数: |
36298 次 |
| 最近记录: |