springboot全局异常处理

1、错误码枚举类

@Getter
@AllArgsConstructor
public enum ServiceExceptionEnum {
    SUCCESS(0, "成功"),
    SYSTEM_ERROR(1001, "服务端异常"),
    CONSTRAINT_VIOLATION(1002, "数据完整性异常"),

    // ========== 用户模块 ==========
    USER_NOT_FOUND(2001002000, "用户不存在"),

    // ========== 订单模块 ==========

    // ========== 商品模块 ==========
    ;
    private int code;

    private String message;

}

2、自定义异常类

@Getter
public class ServiceException extends RuntimeException{
    /**
     * 错误码
     */
    private final Integer code;

    public ServiceException(ServiceExceptionEnum serviceExceptionEnum) {
        // 使用父类的 message 字段
        super(serviceExceptionEnum.getMessage());
        // 设置错误码
        this.code = serviceExceptionEnum.getCode();
    }
}

3、全局异常处理

@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 处理 ServiceException 异常
     */
    @ResponseBody
    @ExceptionHandler(value = ServiceException.class)
    public Result serviceExceptionHandler(HttpServletRequest req, ServiceException ex) {
        log.debug("[serviceExceptionHandler]", ex);
        // 包装 Result 结果
        return Result.error(ex.getCode(), ex.getMessage());
    }



    /**
     * 处理其它 Exception 异常
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public Result exceptionHandler(HttpServletRequest req, Exception e) {
        // 记录异常日志
        log.error("[exceptionHandler]", e);
        // 返回 ERROR Result
        return Result.error(ServiceExceptionEnum.SYSTEM_ERROR.getCode(),
                ServiceExceptionEnum.SYSTEM_ERROR.getMessage());
    }
}

测试在controller中抛出异常

    @RequestMapping("test1")
    public Result test1(){

        throw new NullPointerException("测试空指针异常");
    }

    /**
     * 测试 ServiceException异常
     * @return
     */
    @RequestMapping("test2")
    public Result test2(){
        throw new ServiceException(ServiceExceptionEnum.CONSTRAINT_VIOLATION);
    }

{
    "code": 1001,
    "message": "服务端异常",
    "data": null
}
{
    "code": 1002,
    "message": "数据完整性异常",
    "data": null
}

5、统一封装返回

@Data
public class Result<T> {

    public static Integer CODE_SUCCESS = 0;

    private int code;

    private String message;

    private T data;

    public static <T> Result<T> error(int code,  String message){
        Result result = new Result();
        result.setCode(code);
        result.setMessage(message);
        return result;
    }

    public static <T> Result<T> success(T data) {
        Result<T> result = new Result<>();
        result.code = CODE_SUCCESS;
        result.data = data;
        result.message = "";
        return result;
    }

}

4、处理业务异常返回Result 还是 throws 异常?

在处理Service层 逻辑异常的时候,通常可以选择返回两种方案:

  • 封装统一的业务异常类 ServiceException ,里面有错误码和错误提示,然后进行 throws 抛出。
  • 封装通用的返回类 Result ,里面有错误码和错误提示,然后进行 return 返回

一般选择抛出ServiceException ,原因

  • 因为 Spring @Transactional 声明式事务,是基于异常进行回滚的,如果使用Result 返回,则事务回滚会非常麻烦。

  • 当调用别的方法时,如果别人返回的是Result 对象,还需要不断的进行判断,写起来挺麻烦的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值