SpringBoot 全局异常处理
为什么要统一异常处理
在日常的开发过程中,有许多的异常需要我们处理,所有异常的父类都是
Throwable
类。其中Exception异常是可以进行手动处理的,在程序运行过程中,也会出现各种业务异常,需要自定义,可能返回500,404,等等,前端拿到这些异常可能不方便处理,如果可以统一一个全局异常,是什么错误就返回什么信息和code码给前端,前端更便于处理。
开始
1. 创建一个异常使用的统一接口
package com.rich.common.exception;
/**
* <p>
* 全局统一异常处理-自定义异常处理接口
* </p>
*
* @author: jinxs
* @since: 2022/9/1 8:53
*/
public interface BaseErrorInfoInterface {
/**
* 获取状态码
* @return
*/
String getCode();
/**
* 获取异常信息
* @return
*/
String getMsg();
}
2. 创建异常错误枚举类
package com.rich.common.enums;
import com.rich.common.exception.BaseErrorInfoInterface;
/**
* <p>
* 全局异常错误枚举类
* </p>
*
* @author: jinxs
* @since: 2022/9/1 9:03
*/
public enum BaseErrorEnum implements BaseErrorInfoInterface {
SUCCESS("200","成功"),
BODY_NOT_MATCH("400","数据格式不匹配"),
NOT_FOUND("404","资源未找到"),
INTERNAL_SERVER_ERROR("500","服务器内部错误!"),
SERVER_BUSY("503","服务器繁忙"),
REQUEST_METHOD_SUPPORT_ERROR("10001","当前请求方法不支持"),
REQUEST_DATA_NULL("10002","当前请求参数为空"),
USER_NOT_EXISTS("10003","用户不存在"),
USER_INVALID("10004","登录信息已失效,请重新登录"),
PASSWORD_ERROR("10005","密码错误"),
USER_NAME_LOCK("10006","账号被锁定");
private String code;
private String msg;
BaseErrorEnum(String code, String msg) {
this.code = code;
this.msg = msg;
}
@Override
public String getCode() {
return this.code;
}
@Override
public String getMsg() {
return this.msg;
}
}
3.创建语出异常处理类
package com.rich.common.exception;
import com.rich.common.enums.BaseErrorEnum;
import lombok.Data;
/**
* <p>
* 全局统一异常基础异常
* </p>
*
* @author: jinxs
* @since: 2022/9/1 9:53
*/
@Data
public class BaseException extends RuntimeException{
/***
* 错误码
*/
private String code;
/**
* 错误消息
*/
private String msg;
/**
* 默认构造
*/
public BaseException() {
super();
}
/**
* 自定义构造
* @param baseErrorEnum
*/
public BaseException(BaseErrorEnum baseErrorEnum){
super(baseErrorEnum.getCode());
this.code = baseErrorEnum.getCode();
this.msg = baseErrorEnum.getMsg();
}
}
说明: 这里的 BaseException 需要继承RuntimeException 而不是Exception原因是RuntimeException是在运行时抛出的在编译的时候不需要做任何处理,而Exception在编译期间就要做响应的处理。如果你throw了一个RuntimeException,不需要做额外操作;而throw一个Exception,程序会要求你try-catch,否则你根本启动不了程序
4. 设计统一结果响应
package com.rich.common.pojo.base;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* <p>
* 基础相应类
* </p>
*
* @author: jinxs
* @since: 2022/9/1 10:09
*/
@Data
@AllArgsConstructor
public class BaseResponse<T> {
private String code;
private String msg;
private T data;
}
package com.rich.common.pojo.base;
import com.rich.common.enums.BaseErrorEnum;
/**
* <p>
* 统一返回
* </p>
*
* @author: jinxs
* @since: 2022/9/1 10:16
*/
public class RespGenerator {
/**
* 正常返回时调用方法
* @param data
* @return
*/
public static BaseResponse success(Object data){
return new BaseResponse(BaseErrorEnum.SUCCESS.getCode(),"接口调用成功!",data);
}
/**
* 失败时调用方法(入参是异常枚举)
* @param baseErrorEnum
* @return
*/
public static BaseResponse<Object>fail(BaseErrorEnum baseErrorEnum){
return new BaseResponse<Object>(baseErrorEnum.getCode(),baseErrorEnum.getMsg(),null);
}
/**
* 调用失败(提供给GLobalExceptionHandler类使用)
* @param code
* @param message
* @return
*/
public static BaseResponse<Object>fail(String code,String message) {
return new BaseResponse<Object>(code, message, null);
}
}
5. 添加全局异常处理类
package com.rich.common.exception;
import com.rich.common.enums.BaseErrorEnum;
import com.rich.common.pojo.base.BaseResponse;
import com.rich.common.pojo.base.RespGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* <p>
* 全局异常处理
* </p>
*
* @author: jinxs
* @since: 2022/9/1 10:02
*/
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
/**
* 处理自定义异常
* @param e
* @return
*/
@ExceptionHandler(value = BaseException.class)
public BaseResponse<Object> baseExceptionHandler(BaseException e) {
log.error("发生业务异常!{}", e.getMsg());
return RespGenerator.fail(e.getCode(), e.getMsg());
}
/**
* 处理空指针异常
* @param e
* @return
*/
@ExceptionHandler(value = NullPointerException.class)
public BaseResponse<Object> exceptionHandler(NullPointerException e) {
log.error("发生空指针异常!{}",e.getMessage());
return RespGenerator.fail(BaseErrorEnum.BODY_NOT_MATCH);
}
/**
* 处理其他异常
* @param e
* @return
*/
@ExceptionHandler(value = Exception.class)
public BaseResponse<Object> exceptionHandler(Exception e) {
log.error("未知异常!{}",e.getMessage());
return RespGenerator.fail(BaseErrorEnum.INTERNAL_SERVER_ERROR);
}
}
说明:
- @RestControllerAdvice注解是@ResponseBody和@ControllerAdvice的组合。
- @ResponseBody注解:通常用来将java对象转成JSON对象,返回给前端JSON数据
- @ControllerAdvice注解:结合方法型注解@ExceptionHandler,用于捕获Controller中抛出的指定类型的异常,从而达到不同类型的异常区别处理的目的。
- @ExceptionHandler注解统一处理某一类异常,从而能够减少代码重复率和复杂度,value值为什么异常类型,就处理什么异常类型的逻辑。
6.测试
结果:
完结!