1 概述
在Spring MVC
框架中,全局异常处理允许你集中处理应用程序中抛出的各种异常,并以一致的方式向客户端返回错误信息。全局异常处理可以增强应用程序的健壮性和用户体验,特别是在Web
应用中。
Spring MVC
中有内置的异常处理对象,但是呈现的结果对于用户端不友好,所以实际项目我们一般会使用全局异常处理器处理异常。
2 注解说明
实现全局异常处理时,常见注解有三个:
-
@ControllerAdvice
注解- 用于描述全局异常处理类。
- 这个类会被
Spring
自动扫描并注册为一个全局异常处理对象。
-
ExceptionHandler
注解:- 用于描述全局异常处理方法
- 描述方法时,需要指定可以处理的异常类型。
-
@RestControllerAdvice
注解- 复合注解,是
@ControllerAdvice
注解和@ResponseBody
注解的组合。
- 复合注解,是
3 全局异常处理器使用流程
-
第1步: 基于异常处理需求,定义全局异常处理类,代码如下:
工程目录下创建base.exception.GlobalExceptionHandler
@RestControllerAdvice
public class GlobalExceptionHandler {
}
-
第2步: 创建对应的异常处理方法
在异常处理方法上添加@ExceptionHandler
注解
/**
ex.getMessage()方法:用于捕获异常信息
*/
@ExceptionHandler
public JsonResult doHandleRuntimeException(RuntimeException ex){
log.error("error is " + ex.getMessage());
return new JsonResult(StatusCode.OPERATION_FAILED,ex.getMessage());
}
4 整体代码
base.exception.GlobalExceptionHandler
package cn.tedu._03vehicle.base.exception;
import cn.tedu._03vehicle.base.response.JsonResult;
import cn.tedu._03vehicle.base.response.StatusCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* RestControllerAdvice 是复合注解,描述的类型为一个全局异常处理对象类型,
* 等价于:@ControllerAdvice+@ResponseBody
* 当某个Controller方法中出现了异常,系统底层就会查找有没有定义全局异常处理对象。
* 这个全局异常处理对象中有没有定义对应的异常处理方法,假如有就调用此方法处理异常。
*/
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
/**
* @ExceptionHandler 描述的方法为一个异常处理方法,在此注解内部可以定义具体的异常处理
* 类型(例如RuntimeException),此注解描述的方法需要定义一个异常类型的形式参数,
* 通过这个参数接收具体的异常对象(也可以接收其异常类型对应的子类类型的异常)。
*/
@ExceptionHandler
public JsonResult doHandleIllegalArgumentException(IllegalArgumentException ex){
log.error("IllegalArgumentException: " + ex.getMessage());
return new JsonResult(StatusCode.OPERATION_FAILED, ex.getMessage());
}
/**
* 假如用全局异常处理对象处理Controller类中出现的异常,全局异常处理对象会优先查找与Controller
* 中相匹配的异常处理方法,假如没有,会查找对应异常的父类异常处理方法。
*/
@ExceptionHandler
public JsonResult doHandleRuntimeException(RuntimeException ex){
log.error("IllegalArgumentException is " + ex.getMessage());
return new JsonResult(StatusCode.OPERATION_FAILED,ex.getMessage());
}
}
5 关于Throwable
在开发实践中,通常会添加一个处理 Throwable
的方法,它将可以处理所有类型的异常,则不会再出现500
错误!
GlobalExceptionHandler
中添加处理 Throwable
的方法
@ExceptionHandler
public JsonResult doHandleThrowable(Throwable ex){
String data = ex.getMessage();
log.error("Throwable:" + data);
return new JsonResult(StatusCode.THROWABLE_ERROR, data);
}
6 注意事项
- 在设计全局异常处理时,请确保异常处理器能够覆盖尽可能多的异常类型。
- 使用恰当的
HTTP
状态码来区分不同类型的错误。 - 提供有用的错误信息,但不要泄露敏感信息。
- 如果可能,记录异常的详细信息以便于调试和追踪问题。