SpringBoot自定义异常,优雅解决业务逻辑中的错误

前言

在我们开发中,总会碰到一些异常 ---------- 运行时异常(不受检异常):RuntimeException类极其子类表示JVM在运行期间可能出现的错误。编译器不会检查此类异常,并且不要求处理异常,比如用空值对象的引用(NullPointerException)、数组下标越界(ArrayIndexOutBoundException)。此类异常属于不可查异常,一般是由程序逻辑错误引起的,在程序中可以选择捕获处理,也可以不处理。
对于这些异常,如果返回给前端,会给用户代码很不好的体验,因为用户不知道 NullPointerException 等异常的意思,只会吐槽我们的项目,严重会导致用户流失,下面我们优雅的解决程序运行中的一场
设计

1. 自定义枚举类

使用枚举统一管理我们的错误信息

enum ResultEnum {

UNKNOWN_ERROR(-100, “未知错误”),
NEED_LOGIN(-1, “未登录”),
REPEAT_REGISTER(-2, “该用户已注册”),
USER_NOT_EXIST(-3, “不存在该用户”),
PASSWORD_ERROR(-4, “密码错误”),
EMPTY_USERNAME(-5, “用户名为空”),
EMPTY_PASSWORD(-6, “密码为空”),
SUCCESS(0, “success”),
SYSTEM_ERROR(500,“手速太快了,慢点”);

private Integer code;

private String msg;

private ResultEnum(Integer code, String msg) {

this.code = code;
this.msg = msg;
}

public Integer getCode() {

return code;
}

public String getMsg() {

return msg;
}
}

2. 自定义异常

package com.yxl.exception;

import com.yxl.enums.ResultEnum;

/**

  • @Author:byteblogs

  • @Date:2018/09/27 12:52
    */
    public class BusinessException extends RuntimeException {

    private int code;

    private String errMsg;

    public BusinessException(ResultEnum resultEnum){
    this.code = resultEnum.getCode();
    this.errMsg = resultEnum.getMsg();
    }

    public Integer getCode() {
    return code;
    }

    public void setCode(Integer code) {
    this.code = code;
    }

    public String getErrMsg() {
    return errMsg;
    }

    public void setErrMsg(String errMsg) {
    this.errMsg = errMsg;
    }
    }

3. 异常全局处理

创建handler文件夹
新增ExcepetionHandler类

加入 @ControllerAdvice 注解
**加粗样式**
对于@ControllerAdvice,我们比较熟知的用法是结合@ExceptionHandler用于全局异常的处理,但其作用不仅限于此。ControllerAdvice拆分开来就是Controller
Advice,关于Advice,前面我们讲解Spring
Aop时讲到,其是用于封装一个切面所有属性的,包括切入点和需要织入的切面逻辑。这里ContrllerAdvice也可以这么理解,其抽象级别应该是用于对Controller进行“切面”环绕的,而具体的业务织入方式则是通过结合其他的注解来实现的。@ControllerAdvice是在类上声明的注解,其用法主要有三点:
结合方法型注解@ExceptionHandler,用于捕获Controller中抛出的指定类型的异常,从而达到不同类型的异常区别处理的目的;

处理全局异常
http://www.sipaiyibiao.com/
ResultBody 是返回的项目统一格式
package com.yxl.handler;

import com.yxl.enums.ResultEnum;
import com.yxl.exception.BusinessException;
import com.yxl.po.ResponseMessage;
import com.yxl.po.ResultBody;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.stream.Collectors;

@ControllerAdvice
public class ExceptionHandler {

private final static Logger logger= LoggerFactory.getLogger(ExceptionHandler.class);

/**
 * 处理其他异常
 * @param e
 * @return
 */
@org.springframework.web.bind.annotation.ExceptionHandler(value = Exception.class)
@ResponseBody
public ResponseMessage handel(Exception e){
    if(e instanceof BusinessException){
        BusinessException myException =(BusinessException)e;
        return ResultBody.error( myException.getCode(),myException.getMessage());
    }else {
        logger.error("[系统异常] {}",e);
        return ResultBody.error(ResultEnum.SYSTEM_ERROR);
    }
}


/**
 * 处理BusinessException异常
 * @param e
 * @return
 */
@org.springframework.web.bind.annotation.ExceptionHandler(value = BusinessException.class)
@ResponseBody
public ResponseMessage busin(BusinessException e) {
    return ResultBody.error(e.getCode(), e.getErrMsg());
}

/**
 * 处理空指针的异常
 *
 * @param req
 * @param e
 * @return
 */
@org.springframework.web.bind.annotation.ExceptionHandler(value = NullPointerException.class)
@ResponseBody
public ResponseMessage exceptionHandler(HttpServletRequest req, NullPointerException e) {
    logger.error("发生空指针异常!原因是:", e);
    return ResultBody.error(ResultEnum.SYSTEM_ERROR);
}
/**
 * 处理参数校验异常
 *
 * @param req
 * @param e
 * @return
 */
@org.springframework.web.bind.annotation.ExceptionHandler(value = MethodArgumentNotValidException.class)
@ResponseBody
public ResponseMessage exceptionHandler(HttpServletRequest req, MethodArgumentNotValidException  e) {

    logger.error("参数校验异常:", e);
    String message = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining());
    return ResultBody.error(ResultEnum.SYSTEM_ERROR);
}

/**
 * 处理参数校验异常 --Json 转换异常
 * @param req
 * @param e
 * @return
 */
@org.springframework.web.bind.annotation.ExceptionHandler(value = HttpMessageNotReadableException.class)
@ResponseBody
public ResponseMessage exceptionHandler(HttpServletRequest req, HttpMessageNotReadableException e) {
    logger.error("参数校验异常-json转换异常:", e);
    return ResultBody.error(ResultEnum.SYSTEM_ERROR);
}

}
4. 使用
@GetMapping("/test2")
public ResponseMessage test2(@ApiParam(value = “id”)@RequestParam(required = false) Long id) {
//如果等于空抛出异常
if(Objects.isNull(id)){
throw new BusinessException(ResultEnum.EMPTY_USERNAME);
}
return ResultBody.success();
}
结果 抛出了我们自定义的枚举异常
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值