SpringBoot整合SpringMVC之全局异常处理

这个例子将模仿抛出各种exception,并包装在CommonResult中进行统一的返回


我们先来给出项目中的错误码的枚举类,这里挖坑,后面填

//枚举项目中的错误码
public enum ServiceExceptionEnum {

//错误码设计的规则
    /**
     * 服务异常
     *
     * 参考 https://www.kancloud.cn/onebase/ob/484204 文章
     *
     * 一共 10 位,分成四段
     *
     * 第一段,1 位,类型
     *      1 - 业务级别异常
     *      2 - 系统级别异常
     * 第二段,3 位,系统类型
     *      001 - 用户系统
     *      002 - 商品系统
     *      003 - 订单系统
     *      004 - 支付系统
     *      005 - 优惠劵系统
     *      ... - ...
     * 第三段,3 位,模块
     *      不限制规则。
     *      一般建议,每个系统里面,可能有多个模块,可以再去做分段。以用户系统为例子:
     *          001 - OAuth2 模块
     *          002 - User 模块
     *          003 - MobileCode 模块
     * 第四段,3 位,错误码
     *       不限制规则。
     *       一般建议,每个模块自增。
     */

    //===========系统级别============
    SUCCESS(0, "成功"),
    SYS_ERROR(2001001000,"服务端发生异常"),
    MISSING_REQUEST_PARAM_ERROR(2001001001,"参数缺失"),

    //===========用户级别============
    USER_NOT_FOUND(1001002000,"用户不存在"),

    //===========订单级别============

    //===========订单级别============
    ;

    /**
     * 错误码
     */
    private int code;

    /**
     * 错误提示
     */
    private String message;

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

    public int getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }
}

这里的返回错误的返回格式也基本是错误码code+错误提示message,这里的错误码设计的原则卸载了注释里面


下面引入与Service逻辑异常有关的错误,这里选择的方式还是,封装通用的返回类

//service中的异常
public final class ServiceException extends RuntimeException{

    /**
     * 错误码
     */
    private final Integer code;

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

    public Integer getCode() {
        return code;
    }
}

这里后续需要补充各种常见异常类这个坑。

这里的意思呢,显然异常类中是有一个message的信息的,然后加上我们自定义的错误码,这里的错误码呢,会引用我们定义的枚举类型中的错误码,说实话,写到这里,我觉得枚举类好像也挺好理解的了,就是封装一连串的final对象,然后就那几个给定的状态,比起普通类来说,多了一个枚举定义的过程。


下一步需要定义一个统一返回的处理器

@ControllerAdvice(basePackages = "com.zzaxg.springboot.controller")
public class GlobalExceptionHandler {

    private Logger logger = LoggerFactory.getLogger(getClass());

    //使用该异常的code+message属性,构建CommonResult对象来返回

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

    /**
     * 处理 MissingServletRequestParameterException 异常
     *
     * SpringMVC参数不正确
     */
    @ResponseBody
    @ExceptionHandler(value = MissingServletRequestParameterException.class)
    public CommonResult MissingServletRequestParameterException(HttpServletRequest request, MissingServletRequestParameterException ex) {
        logger.debug("[missingServletRequestParameterException]", ex);
        //包装CommonResult结果
        return CommonResult.error(ServiceExceptionEnum.MISSING_REQUEST_PARAM_ERROR.getCode(), ServiceExceptionEnum.MISSING_REQUEST_PARAM_ERROR.getMessage());
    }

    //兜底的异常处理

    /**
     * 处理其他 Exception 异常
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public CommonResult exceptionHandler(HttpServletRequest request, Exception e) {
        //记录异常日志
        logger.debug("[exceptionHandler]", e);
        //包装CommonResult结果
        return CommonResult.error(ServiceExceptionEnum.SYS_ERROR.getCode(), ServiceExceptionEnum.SYS_ERROR.getMessage());
    }

}

同样是定义了可一个切面,但这里不需要拦截接口返回结果,所以不需要定义ResponseBodyHandler接口

通过@ExceptionHandler注解定义每个方法对应处理的异常,@ResponseBody注解呢,标记直接使用返回结果作为API的响应

这里的logger.debug呢,打印了错误日志


下面写一个controller进行错误的throw

/**
     * 测试抛出NullPointerException异常
     *
     * @return
     */
    @GetMapping("/exception-01")
    public UserVO exception01() {
        throw new NullPointerException("周周不在呢");
    }

    /**
     * 测试抛出ServiceException异常
     *
     */
    @GetMapping("/exception-02")
    public UserVO exception02() {
        throw new ServiceException(ServiceExceptionEnum.USER_NOT_FOUND);
    }

返回的结果呢,分别是

{
    "code": 2001001000,
    "message": "服务端发生异常",
    "data": null
}
{
    "code": 1001002000,
    "message": "用户不存在",
    "data": null
}

原文参考芋道源码

谢谢观看

你可能感兴趣的:(springboot,springMVC)