Java全局异常处理+自定义异常
  RuXuq8CpAyRj 2023年12月07日 24 0


目录



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

定义通用结果返回类

定义错误码

定义返回工具类

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

全局异常处理类

验证全局异常处理器


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

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的博客

/**
 * @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());
    }
}

验证全局异常处理器

postman调用后端接口

Java全局异常处理+自定义异常_开发语言

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

Java全局异常处理+自定义异常_开发语言_02

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

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

 今天的分享就先到这里,文章有哪些不足之处,欢迎指出!!!

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年12月07日 0

暂无评论

推荐阅读
  xaeiTka4h8LY   2024年05月17日   51   0   0 数据库JavaSQL
  2iBE5Ikkruz5   2023年12月12日   92   0   0 JavaJavaredisredis
RuXuq8CpAyRj