Spring Boot全局异常
1 @ControllerAdvice
@ExceptionHandler(Exception.class)
注解,表示当控制器抛出Exception异常时,将会委托该方法来处理。
@controllerAdvice
最为实用的一个场景就是将所有@ExceptionHandler方法收集到一个类中,这样所有的异常都能在一个地方进行一致处理。
@ControllerAdvice
默认所有控制的抛出的异常都会在这个类进行处理
-
@ControllerAdvice
是一个@Component
,用于定义@ExceptionHandler,@InitBinder和@ModelAttribute
方法,适用于所有使用@RequestMapping
方法。 -
在Spring中,
@ControllerAdvice
通过annotations(), basePackageClasses(), basePackages()
方法定制用于选择控制器子集。 -
即把
@ControllerAdvice
注解内部使用@ExceptionHandler、@InitBinder、@ModelAttribute
注解的方法应用到所有的@RequestMapping
注解的方法。非常简单,不过只有当使用@ExceptionHandler
最有用,另外两个用处不大。
1.1 basePackages
@ControllerAdvice同时配置过滤多个包
//@ControllerAdvice("com.test.controller") //配置过滤一个的时候
//@ControllerAdvice(value = "cn.test.controller")
@ControllerAdvice(basePackages={"com.test.controller", "com.test1.controller"}) //同时配置过滤多个包
public class GlobalExceptionHandler {
···········
}
basePackages
:指定一个或多个包,这些包及其子包下的所有 Controller 都被该 @ControllerAdvice 管理。其中上面两种等价于 basePackages。
1.2 basePackageClasses
@ControllerAdvice(basePackageClasses = {MyController1.class})
public class GlobalExceptionHandler {}
basePackageClasses
:是 basePackages 的一种变形,指定一个或多个 Controller 类,这些类所属的包及其子包下的所有 Controller 都被该 @ControllerAdvice 管理。
1.3 assignableTypes
@ControllerAdvice(assignableTypes = {MyController1.class})
public class GlobalExceptionHandler {}
assignableTypes
:指定一个或多个 Controller 类,这些类被该 @ControllerAdvice 管理。即被{}
起来的 {MyController1.class}
这个类被全局异常监控。
1.4 annotations
@ControllerAdvice(annotations = {RestController.class})
public class GlobalExceptionHandler {}
annotations
:指定一个或多个注解,被这些注解所标记的 Controller 会被该 @ControllerAdvice 管理。
2 示例
这里用 assignableTypes 配置指定的 Controller 进行测试。
创建三个 Controller
@Controller
public class MyController1 {
@RequestMapping(value = "/test1")
public void test1() {
throw new BusinessException("1", "test1 错误");
}
}
@Controller
public class MyController2 {
@RequestMapping(value = "/test2")
public void test1() {
throw new BusinessException("2", "test2 错误");
}
}
@Controller
public class MyController3 {
@RequestMapping(value = "/test3")
public void test1() {
throw new BusinessException("3", "test3 错误");
}
}
其中,BusinessException 是我自定义的异常类。
创建两个全局异常处理类
@ControllerAdvice(assignableTypes = {MyController1.class})
@Slf4j
public class GlobalExceptionHandler1 {
/**
* 处理 Exception 异常
* @param httpServletRequest request
* @param e 异常
* @return
*/
@ResponseBody
@ExceptionHandler(value = Exception.class)
public String exceptionHandler(HttpServletRequest request, Exception e) {
log.error("GlobalExceptionHandler1 服务错误");
return "GlobalExceptionHandler1 服务错误";
}
}
@ControllerAdvice(assignableTypes = {MyController2.class})
@Slf4j
public class GlobalExceptionHandler2 {
/**
* 处理 Exception 异常
* @param httpServletRequest request
* @param e 异常
* @return
*/
@ResponseBody
@ExceptionHandler(value = Exception.class)
public String exceptionHandler(HttpServletRequest request, Exception e) {
log.error("GlobalExceptionHandler2 服务错误");
return "GlobalExceptionHandler2 服务错误";
}
}
分别调用接口,查看错误日志
-
调用 localhost:8080/test1
返回:GlobalExceptionHandler1 服务错误
即 MyController1 异常被 GlobalExceptionHandler1 全局异常类捕获。 -
调用 localhost:8080/test2
返回:GlobalExceptionHandler2 服务错误
即 MyController2 异常被 GlobalExceptionHandler2 全局异常类捕获。 -
调用 localhost:8080/test3
其中调用3返回下面的提示:
即 MyController3 异常没有被全局异常捕获。
{
"timestamp": "2021-06-18T16:01:06.224+0000",
"status": 500,
"error": "Internal Server Error",
"message": "No message available",
"path": "/test3"
}
参考:https://blog.csdn.net/abckingaa/article/details/89601060
https://www.interhorse.cn/a/799497670/
Spring 框架 5.1.5.RELEASE API
https://www.cnblogs.com/duanxz/p/3753687.html