Java全局异常捕捉

1.场景还原

     在项目开发中,对于各种异常都有不同的报错提示或策略,无疑对于用户或者开发来说,是一个很好的用户体验;如何在java定义一个全局异常捕捉呢? 

2.实现方案

2.1 自定义一个业务异常类

@Setter
@Getter
public class BizException extends RuntimeException {

    private static final long serialVersionUID = -6233506444097954612L;
    /**
     * 错误码
     */
    private String errorCode;
    /**
     * 错误信息
     */
    private String errorMsg;

    /**
     * 返回错误对象信息
     */
    private Object data;

    public BizException() {
        super();
    }

    public BizException(String errorMsg) {
        super(errorMsg);
        this.errorMsg = errorMsg;
    }

    public BizException(String errorCode, String errorMsg) {
        super(errorCode);
        this.errorCode = errorCode;
        this.errorMsg = errorMsg;
    }

    public BizException(String errorCode, String errorMsg, Throwable cause) {
        super(errorCode, cause);
        this.errorCode = errorCode;
        this.errorMsg = errorMsg;
    }

    public BizException(ResultEnum resultEnum) {
        super(resultEnum.code());
        this.errorCode = resultEnum.code();
        this.errorMsg = resultEnum.message();
    }

    public BizException(ResultEnum resultEnum, Throwable cause) {
        super(resultEnum.code(), cause);
        this.errorCode = resultEnum.code();
        this.errorMsg = resultEnum.message();
    }

    public BizException(ResultEnum resultEnum, Object data) {
        this.errorCode = resultEnum.code();
        this.errorMsg = resultEnum.message();
        this.data = data;
    }
}

2.2 定义一个错误枚举类

public enum ResultEnum {
   
    SUCCESS("200", "success"),
  
    FAIL("0", "failed"),
  
    PARAM_INVALID("-1", "param is invalid");

    private String code;

    private String message;

    ResultEnum(String code, String message){
        this.code = code;
        this.message = message;
    }

    public String code(){
        return this.code;
    }

    public String message(){
        return this.message;
    }

}

2.3 定义一个全局异常捕捉类

@Slf4j
@ResponseBody
@ControllerAdvice
public class GlobalExceptionHandler {
    /**
     * 处理自定义的业务异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = BizException.class)
    public RestResponse bizExceptionHandler(BizException e) {
        log.error("业务异常!原因:{}", e.getErrorMsg());
        return RestResponse.fail(e.getErrorCode(), e.getErrorMsg());
    }

    /**
     * 处理空指针的异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = NullPointerException.class)
    public RestResponse exceptionHandler(NullPointerException e) {
        log.error("空指针异常!原因:{}", e);
        return RestResponse.fail("空指针异常");
    }

 @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public RestResponse exceptionHandler(Exception e) {
        StringBuilder errMsg = new StringBuilder();
        // 方法参数无效 异常
        if (e instanceof MethodArgumentNotValidException) {
            BindingResult bindResult = ((MethodArgumentNotValidException) e).getBindingResult();
            List<FieldError> fieldErrorList = bindResult.getFieldErrors();
            fieldErrorList.forEach(fieldErrors -> {
                if (StringUtils.isNotBlank(errMsg.toString())) {
                            errMsg.append(",");
                        }
                        errMsg.append(fieldErrors.getDefaultMessage());
                    }
            );

        } else {
            return RestResponse.fail(ResultEnum.INTERNAL_ERROR);
        }

        return RestResponse.fail(errMsg.toString());
    }

}

2.4 定义一个restful response类

@Setter
@Getter
public class RestResponse {

    private String code;

    private String message;

    private Object data;

    public RestResponse(){

    }

    public static RestResponse success(){
        RestResponse restResponse = new RestResponse();
        restResponse.setResultCode(ResultEnum.SUCCESS);

        return restResponse;
    }

    public static RestResponse success(Object data){
        RestResponse restResponse = new RestResponse();
        restResponse.setResultCode(ResultEnum.SUCCESS);
        restResponse.setData(data);

        return restResponse;
    }

    public static RestResponse fail() {
        RestResponse restResponse = new RestResponse();
        restResponse.setResultCode(ResultEnum.FAIL);

        return restResponse;
    }


    public static RestResponse fail(ResultEnum resultEnum) {
        RestResponse restResponse = new RestResponse();
        restResponse.setResultCode(resultEnum);

        return restResponse;
    }

    public static RestResponse fail(String message) {
        RestResponse restResponse = new RestResponse();
        restResponse.setCode(ResultEnum.FAIL.code());
        restResponse.setMessage(message);

        return restResponse;
    }

    public static RestResponse fail(String code, String message) {
        RestResponse restResponse = new RestResponse();
        restResponse.setCode(code);
        restResponse.setMessage(message);

        return restResponse;
    }

    public static RestResponse fail(ResultEnum resultEnum, Object data) {
        RestResponse restResponse = new RestResponse();
        restResponse.setResultCode(resultEnum);
        restResponse.setData(data);

        return restResponse;
    }

    private void setResultCode(ResultEnum resultEnum){
        this.code = resultEnum.code();
        this.message = resultEnum.message();
    }


}

2.5 从service或controller抛出具体异常

@GetMapping("/getInfo")
    @ApiOperation(value = "get user info api")
    public RestResponse getUserInfo(HttpServletRequest request) {
      
       return RestResponse.fail(ResultEnum.USER_NOY_EXISTS);
    }

本文主要@ControllerAdvice+@ExceptionHandler两个注解结合实现全局异常捕捉,对于两个注解的原理,有兴趣的同学可以去研究下底层是怎么工作的,我这里就不再赘述!

猜你喜欢

转载自blog.csdn.net/zhangxing52077/article/details/108152413