Java 全局异常处理 + 自定义异常

全局异常处理

为什么使用统一异常处理?

1.软件开发过程中,不可避免的是需要处理各种异常,就我自己来说,至少有一半以上的时间都是在处理各种异常情况,所以代码中就会出现大量的try {…} catch {…} finally {…} 代码块,不仅有大量的冗余代码,而且还影响代码的可读性。

2.使用统一结果处理时,有些异常我们可以提前预知并处理,但是一个运行时异常,我们不一定能预知并处理,这时可以使用统一异常处理,当异常发生时,触发该处理操作,从而保证程序的健壮性

定义通用结果返回类

为了规范后台开发接口的标准,以及便于前台统一处理接口返回数据,定义一个通用的返回类是必要的。

/**
 * @Author: Ambation
 * @Description: 通用返回类
 * @Date Created in 2023-02-04-20:57
 * @Modified By:
 */
@Data
public class BaseResponse<T> implements Serializable {
    private static final long serialVersionUID = -2243004256529006189L;
 
    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 code) {
        this(code.getCode(),null,code.getMessage(),code.getDescription());
    }
}
定义错误码

可分类自定义错误编码,这样可以统一管理(尽量不要跟请求返回的状态码保持一直,比如500,400,404等)

/**
 * @Author: Ambation
 * @Description: 错误码
 * @Date Created in 2023-02-04-21:18
 * @Modified By:
 */
public enum ErrorCode{
 
    SUCCESS(0,"ok",""),
    PARAM_ERROR(40000,"请求参数错误",""),
    NULL_ERROR(40001,"数据为空",""),
    NULL_AUTH(40101,"无权限",""),
    NOT_LOGIN(40100,"未登录",""),
    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;
    }
}
定义返回工具类

减少重复new BaseResponse 返回类,使代码更加简洁

/**
 * @Author: Ambation
 * @Description: 返回工具类
 * @Date Created in 2023-02-04-21:04
 * @Modified By:
 */
public class ResultUtils {
 
    /**
     * 成功
     * @param data
     * @param <T>
     * @return
     */
    public static<T> BaseResponse<T> success(T data){
        return new BaseResponse<T>(0,data,"ok");
    }
 
    /**
     * 失败
     * @param errorCode
     * @return
     */
    public static BaseResponse error(ErrorCode errorCode){
        return new BaseResponse<>(errorCode);
    }
 
    /**
     * 失败
     * @param errorCode
     * @return
     */
    public static BaseResponse error(ErrorCode errorCode,String message,String descrition){
        return new BaseResponse<>(errorCode.getCode(),null,message,descrition);
    }
 
    /**
     * 失败
     * @param errorCode
     * @return
     */
    public static BaseResponse error(ErrorCode errorCode,String message){
        return new BaseResponse<>(errorCode.getCode(),message);
    }
 
    /**
     * 失败
     * @param errorCode
     * @return
     */
    public static BaseResponse error(int errorCode,String message,String descrition){
        return new BaseResponse<>(errorCode,null,message,descrition);
    }
}
作用展示:

使用返回结果公共类的方法:

 @PostMapping("/register")
    @ApiOperation("用户注册")
    public BaseResponse<Long> userRegister(@RequestBody UserRegisterRequest userRegisterRequest) {
        if (Objects.isNull(userRegisterRequest)) {
            throw new BusinessException(ErrorCode.PARAM_ERROR);
        }
        String userAccount = userRegisterRequest.getUserAccount();
        String userPassword = userRegisterRequest.getUserPassword();
        String checkPassword = userRegisterRequest.getCheckPassword();
        String planetCode = userRegisterRequest.getPlanetCode();
        if (StringUtils.isAnyBlank(userAccount, userPassword, checkPassword,planetCode)) {
            throw new BusinessException(ErrorCode.PARAM_ERROR);
        }
        long id = userService.userRegister(userAccount, userPassword, checkPassword, planetCode);
        return ResultUtils.success(id);
    }

未使用返回结果公共类的方法:

 @PostMapping("/register")
    @ApiOperation("用户注册")
    public BaseResponse<Long> userRegister(@RequestBody UserRegisterRequest userRegisterRequest) {
        if (Objects.isNull(userRegisterRequest)) {
            throw new BusinessException(ErrorCode.PARAM_ERROR);
        }
        String userAccount = userRegisterRequest.getUserAccount();
        String userPassword = userRegisterRequest.getUserPassword();
        String checkPassword = userRegisterRequest.getCheckPassword();
        String planetCode = userRegisterRequest.getPlanetCode();
        if (StringUtils.isAnyBlank(userAccount, userPassword, checkPassword,planetCode)) {
            throw new BusinessException(ErrorCode.PARAM_ERROR);
        }
        long id = userService.userRegister(userAccount, userPassword, checkPassword, planetCode);
        return new BaseResponse<>(0, id, null);
    }

对比上面两个方法,可以看出第二个方法,每次都要new 一个 BaseResponse 是不是很麻烦,代码看起来也不够整洁。使用返回结果公共类,可以方便管理各种请求返回结果,代码也更加美观。

自定义异常类(可根据业务需求进行扩展)

java有那么多异常类,为啥还要自定义异常?

Java虽然提供了丰富的异常处理类,但是在项目中还会经常使用自定义异常,其主要原因是Java提供的异常类在某些情况下还是不能满足实际需求。例如以下情况:
1、系统中有些错误是符合Java语法,但不符合业务逻辑。
2、在分层的软件结构中,通常是在表现层统一对系统其他层次的异常进行捕获处理。

例如导数据的项目,向Map中存数据,如果最后Map为空,则认为是业务逻辑错误,直接抛出自定义异常,程序结束,并且可显示具体的错误信息。

Java异常详解之异常基础_Big_Ambation的博客-CSDN博客

/**
 * @Author: Ambation
 * @Description: 自定义异常类
 * @Date Created in 2023-02-04-21:27
 * @Modified By:
 */
public class BusinessException extends RuntimeException{
 
    private final int code;
 
    private final String description;
 
    public BusinessException(String message, int code, String description) {
        super(message);
        this.code = code;
        this.description = 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;
    }
}

全局异常处理类

/**
 * @Author: Ambation
 * @Description:
 * @Date Created in 2023-02-04-21:53
 * @Modified By:
 */
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
       
    //捕获自定义异常
    @ExceptionHandler(BusinessException.class)
    public BaseResponse businessException(BusinessException e) {
        log.error("BusinessException:"+ e.getMessage(), e);
        return ResultUtils.error(e.getCode(), e.getMessage(),e.getDescription());
    }
       
    //捕获所有运行时异常
    @ExceptionHandler(RuntimeException.class)
    public BaseResponse runtimeExceptionException(RuntimeException e) {
        log.error("RuntimeException", e);
        return ResultUtils.error(ErrorCode.SYSTEM_ERROR, e.getMessage());
    }
}

 当前用户为空,手动抛出异常

 进入全局异常处理器,并返回指定的错误信息

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值