我有一个带有REST方法的控制器类,该类可能引发各种异常。我决定使用@ControllerAdvice和@ExceptionHandler作为我的处理程序方法在单独的类中处理这些异常。 但是,我有一个问题,我的REST方法使用另一个库中的注释。该库捕获了我的REST方法也抛出的异常。 现在,我正在全局处理异常,而不是直接通过REST方法中的try / catch处理异常,我的异常始终由其他库而不是由我自己的处理程序方法捕获。显然,由于注释,我正在使用的库中的其他方法胜出。 如何将异常处理绑定到我自己的类上,以防止其他人捕获它?
我的REST方法:
@SomeLibraryAnnotation
@PostMapping(path = "/add", consumes = MediaType.APPLICATION_JSON_VALUE)
public HttpEntity< ? > addItem(@RequestHeader HttpHeaders headers, @RequestBody MyDTO myDTO)
throws UnsupportedOperationException {
doSomethingWith(myDTO);
return ResponseEntity.status(HttpStatus.CREATED).build();
}
我的异常处理程序类:
@ControllerAdvice
public class MyExceptionHandler {
@ExceptionHandler(UnsupportedOperationException.class)
public ResponseEntity<?> handleUnsupportedOperationException(UnsupportedOperationException e) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(e.getMessage());
}
}
由于库方法也捕获了UnsupportedOperationException,因此它由于@SomeLibraryAnnotation而获胜,并且从未在我的处理程序类中处理异常。
答案 0 :(得分:0)
您可以尝试在@Order
类中使用@Priority
或MyExceptionHandler
,如Setting Precedence of Multiple @ControllerAdvice @ExceptionHandlers中所述。
这将使Spring有机会使用您的类,而不是@SomeLibraryAnnotation
指定的类。但是,在不知道Spring如何在上下文初始化时解释其他注释的情况下,这只是一个猜测。
答案 1 :(得分:0)
您是否尝试在控制器内部编写@ExceptionHandler
?喜欢:
@RestController
@RequestMapping("/path")
public class TheController {
@ExceptionHandler(UnsupportedOperationException.class)
public ResponseEntity<?> handleUnsupportedOperationException(UnsupportedOperationException e) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(e.getMessage());
}
}
也许这会优先处理和例外。很难不知道@SomeLibraryAnnotation
是什么...
答案 2 :(得分:0)
这些仅仅是Java语言规则,即,异常不再是 unhandled ,因为它是由其他库处理的(捕获在catch块中)。您可以做的是在库中重新引发(可能有条件地)捕获原始异常的另一个异常,并查看@ExceptionHandler
是否可以处理它。可能不是因为@ExceptionHandler
正在处理Controller类中引发的异常。
第二种方法是抛出仅在@ExceptionHandler中处理的异常,然后将其重新抛出在其他库中处理。
换句话说,您需要选择首先处理最初引发的异常的位置。
第三种方法是使用AOP拦截器@AfterThrowing
或@Around
,然后执行您想要的任何逻辑。
本质:无法同时在两个地方处理异常。有道理吗?