前言
当我们在开发过程中,会因为一些异常程序出现500,如果直接显示给客户看,这样很不友好。并且对我们后期维护,排查bug很困难。
准备
1.创建一个SpringBoot项目,引入web依赖,我们就可以搭建测试,正式开始。
一、全局异常捕获处方式
SpringBoot中,@ControllerAdvice 即可开启全局异常处理,该注解指开启了全局异常的捕获,我们需要在一个自定义方法上使用@ExceptionHandler注解,然后定义捕获异常的类型,就可以对这些捕获的异常进行统一的处理。
//全局异常处理类
@ControllerAdvice
@ResponseBody
public class GlobalException {
@ExceptionHandler(ArithmeticException.class)
public String arithmeticException(ArithmeticException e){
return e.getMessage();
}
}
//测试全局异常处理类
@RestController
public class ExceptionController {
@RequestMapping("/testException")
public String testException(){
System.out.println(1/0);
return "testException";
}
}
结果:/ by zero
注解解释
@ControllerAdvice
@ControllerAdvice注解是Spring3.2中新增的注解,学名是Controller增强器,作用是给Controller控制器添加统一的操作或处理
@ExceptionHandler
@ExceptionHandler注解我们一般是用来自定义异常的。
可以认为它是一个异常拦截器(处理器)。
二、优化
我们不仅可以监听系统的异常,也可以监听自己抛出的异常。并且上面返回的信息,非专业人员看不懂,对返回信息进行优化。
1.ErrorCode 是一个枚举,用于定义各种异常情况。
/**
* 错误码
*/
public enum ErrorCode {
SUCCESS(0,"ok",""),
PARAMS_ERROR(40000,"请求参数错误",""),
NULL_ERROR(40001,"请求数据为空",""),
NOT_LOGIN(40100,"未登录",""),
NO_AUTH(40101,"无权限",""),
SYSTEM_ERROR(50000,"系统内部异常","");
/**
* 状态码信息
*/
private final int code;
/**
* 状态码信息
*/
private final String message;
/**
* 状态码描述(详情)
*/
private final String description;
ErrorCode(int code, String message, String description) {
this.code = code;
this.message = message;
this.description = description;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
public String getDescription() {
return description;
}
}
2.定义一个通用返回类:用于返回给前端的一个框架。
/**
* 通用返回类
* @param <T>
*/
@Data
public class BaseResponse<T> implements Serializable {
private int code;
private T data;
private String message;
private String description;
public BaseResponse(int code, T data, String message,String description) {
this.code = code;
this.data = data;
this.message = message;
this.description = description;
}
public BaseResponse(int code, T data,String message) {
this(code,data,message,"");
}
public BaseResponse(int code, T data) {
this(code,data,"","");
}
public BaseResponse(ErrorCode errorCode){
this(errorCode.getCode(),null,errorCode.getMessage(),errorCode.getDescription());
}
}
3.封装异常:定义我们自己的异常类,然后我们针对一些异常情况进行抛出提示用户。
/**
* 自定义异常类
*/
public class BusinessException extends RuntimeException{
private final int code;
private final String description;
public BusinessException(ErrorCode errorCode) {
super(errorCode.getMessage());
this.code = errorCode.getCode();
this.description = errorCode.getDescription();
}
public BusinessException(ErrorCode errorCode,String description) {
super(errorCode.getMessage());
this.code = errorCode.getCode();
this.description = description;
}
public int getCode() {
return code;
}
public String getDescription() {
return description;
}
}
4.定义返回工具类:对BaseResponse进行一个工具类封装。
/**
* 返回工具类
* @author zwl
*/
public class ResultUtils {
/**
* 成功
* @param data
* @param <T>
* @return
*/
public static <T>BaseResponse<T> success(T data){
return new BaseResponse<>(0,data,"ok");
}
/**
* 失败
* @param errorCode
* @return
*/
public static BaseResponse error(ErrorCode errorCode){
return new BaseResponse<>(errorCode);
}
/**
* 失败
* @param code
* @param message
* @param description
* @return
*/
public static BaseResponse error(int code,String message,String description){
return new BaseResponse(code,null,message,description);
}
/**
* 失败
* @param errorCode
* @param message
* @param description
* @return
*/
public static BaseResponse error(ErrorCode errorCode,String message,String description){
return new BaseResponse(errorCode.getCode(),null,message,description);
}
/**
* 失败
* @param errorCode
* @param description
* @return
*/
public static BaseResponse error(ErrorCode errorCode,String description){
return new BaseResponse(errorCode.getCode(),errorCode.getMessage(),description);
}
}
5.定义全局异常处理类
/**
* 全局异常处理器
*/
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
@ExceptionHandler(BusinessException.class)//全局捕获这个异常进行处理
public BaseResponse businessExceptionHandler(BusinessException e){
log.error("businessException:"+e.getMessage(),e);
return ResultUtils.error(e.getCode(),e.getMessage(),e.getDescription());
}
}
6.抛出异常
//可以不加,因为访问直接是employee
@PostMapping
public R memberAdd(HttpServletRequest request,@RequestBody Employee employee){
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
返回结果
{"code":40000,"data":null,"message":"请求参数错误","description":""}