Java @仅当存在';没有异常的映射
使用spring-web-4.2.6,我有以下控制器和异常处理程序:Java @仅当存在';没有异常的映射,java,spring,spring-mvc,exception,exception-handling,Java,Spring,Spring Mvc,Exception,Exception Handling,使用spring-web-4.2.6,我有以下控制器和异常处理程序: @ControllerAdvice public class ExceptionsHandler { @ExceptionHandler(Exception.class) public ResponseEntity<ErrorDTO> HandleDefaultException(Exception ex) { ... } @ExceptionHandler(Interna
@ControllerAdvice
public class ExceptionsHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorDTO> HandleDefaultException(Exception ex) {
...
}
@ExceptionHandler(InternalError.class)
public ResponseEntity<ErrorDTO> HandleInternalError(InternalError ex) {
...
}
}
@RestController
@RequestMapping("/myController")
public class MyController {
@RequestMapping(value = "/myAction", method = RequestMethod.POST)
public boolean myAction() {
throw new InternalError("");
}
}
@ControllerAdvice
公共类异常处理程序{
@ExceptionHandler(Exception.class)
公共响应处理的默认异常(异常ex){
...
}
@ExceptionHandler(InternalError.class)
公共响应HandleInternalError(InternalError ex){
...
}
}
@RestController
@请求映射(“/myController”)
公共类MyController{
@RequestMapping(value=“/myAction”,method=RequestMethod.POST)
公共布尔myAction(){
抛出新的内部错误(“”);
}
}
出于某种原因,将调用ExceptionHandler的HandleDefaultException(对于Exception.class)方法,而不是HandleInternalError调用类型为NestedServletException的异常
删除默认调用时,将使用正确的InternalError异常调用IntenalError调用
我不想删除默认调用,因为拥有一个默认处理程序对我来说很重要,这样可以为我的用户提供更好的体验
我错过了什么
编辑:
显然,我在使用spring-web-4.3.3,没有要求它。我不明白为什么,这是我的Gradle dependencies树:Spring MVC应该只展示您在4.3及以上版本中描述的行为。看见以前,SpringMVC不会向
@ExceptionHandler
方法公开任何可丢弃的
值。看
从4.3开始,Spring MVC将捕获从处理程序方法抛出的任何
可丢弃的
,并将其包装在NestedServletException
中,然后将其公开给正常的ExceptionHandlerExceptionResolver
过程
下面简要介绍一下它的工作原理:
@Controller
类是否包含任何@ExceptionHandler
方法李>
异常
类型的异常(包括NestedServletException
)。如果可以,它会使用它(如果找到多个匹配项,则会进行排序)。如果不能,并且异常
有一个异常,它将打开并再次尝试查找该异常的处理程序。原因现在可能是可丢弃的(或其任何子类型)李>
@ControllerAdvice
类,并尝试在这些类中找到异常
类型(包括NestedServletException
)的处理程序。如果可以的话,它会使用它。如果不能,并且异常
有一个原因
,它将打开该异常,然后使用该可丢弃类型重试
MyController
抛出一个内部错误
。由于这不是Exception
的子类,SpringMVC将其包装在NestedServletException
中
MyController
没有任何@ExceptionHandler
方法,因此Spring MVC跳过它。您有一个@ControllerAdvice
注释类,exceptionhandler
,因此Spring MVC会对此进行检查。@ExceptionHandler
注释的HandleDefaultException
方法可以处理异常
,因此Spring MVC选择它来处理NestedServletException
如果删除HandleDefaultException
,Spring MVC将找不到可以处理异常的内容。然后,它将尝试打开NestedServletException
,并检查其原因。然后,它将找到可以处理该内部错误的HandleInternalError
这不是一个容易处理的问题。以下是一些选项:
创建一个处理NestedServletException的@ExceptionHandler
,并自己检查内部错误
@ExceptionHandler(NestedServletException.class)
public ResponseEntity<String> HandleNested(NestedServletException ex) {
Throwable cause = ex.getCause();
if (cause instanceof InternalError) {
// deal with it
} else if (cause instanceof OtherError) {
// deal in some other way
}
}
现在Spring将首先尝试在MyController
中找到NestedServletException
的处理程序。它找不到任何异常,因此它将打开NestedServletException
,并获得一个InternalError
。它将尝试查找InternalError
的处理程序,并查找HandleInternalError
这样做的缺点是,如果多个控制器的处理程序方法抛出InternalError
,则必须向每个控制器添加@ExceptionHandler
。这也可能是一个优势。您的处理逻辑将更接近抛出错误的对象。您确定使用的是4.2.6吗?您描述的行为应该只适用于4.3+。显然,我使用的是spring-web-4.3.3,没有要求它。我不明白为什么,这是我的Gradle dependencies树:假设我使用4.3.3,我可以创建两个带有@ControllerAdvice的类,一个用于特定异常(如InternalError),一个用于默认异常,然后让带有特定异常的类先启动吗?我最终创建了两个带有@Order(1)的@ControllerAdvice类特殊例外情况和一般例外情况的顺序(2)。
@RestController
@RequestMapping("/myController")
public class MyController {
@RequestMapping(value = "/myAction", method = RequestMethod.POST)
public boolean myAction() {
throw new InternalError("");
}
@ExceptionHandler(value = InternalError.class)
public ResponseEntity<String> HandleInternalError(InternalError ex) {
...
}
}