up:: 定义通用的返回对象之返回正确的信息

说明:前面我们统一返回了处理成功的信息,这里我们处理异常错误的信息:

定义返回统一错误接口

package com.imooc.miaoshaproject.error;
 
/**
 * Created by hzllb on 2018/11/13. */public interface CommonError {
    public int getErrCode();
    public String getErrMsg();
    public CommonError setErrMsg(String errMsg);
 
 
}

说明:

这里抛出具体错误的方法后面会讲,先看下去,体会一下:

创建抛出统一错误类,继承Exception,实现接口CommonError

package com.imooc.miaoshaproject.error;
 
/**
 * Created by hzllb on 2018/11/13. *///包装器业务异常类实现
public class BusinessException extends Exception implements CommonError {
 
    private CommonError commonError;
 
    //直接接收EmBusinessError的传参用于构造业务异常
    public BusinessException(CommonError commonError){
        super();
        this.commonError = commonError;
    }
 
    //接收自定义errMsg的方式构造业务异常
    public BusinessException(CommonError commonError,String errMsg){
        super();
        this.commonError = commonError;
        this.commonError.setErrMsg(errMsg);
    }
 
 
 
 
 
    @Override
    public int getErrCode() {
        return this.commonError.getErrCode();
    }
 
    @Override
    public String getErrMsg() {
        return this.commonError.getErrMsg();
    }
 
    @Override
    public CommonError setErrMsg(String errMsg) {
        this.commonError.setErrMsg(errMsg);
        return this;
    }
 
    public CommonError getCommonError() {
        return commonError;
    }
}

说明:

枚举异常,分为通用异常和具体异常

package com.imooc.miaoshaproject.error;
 
/**
 * Created by hzllb on 2018/11/13. */public enum EmBusinessError implements CommonError {
    //通用错误类型10001
    PARAMETER_VALIDATION_ERROR(10001,"参数不合法"),
    UNKNOWN_ERROR(10002,"未知错误"),
 
    //20000开头为用户信息相关错误定义
    USER_NOT_EXIST(20001,"用户不存在"),
    USER_LOGIN_FAIL(20002,"用户手机号或密码不正确"),
    USER_NOT_LOGIN(20003,"用户还未登陆"),
 
    //30000开头为交易信息错误定义
    STOCK_NOT_ENOUGH(30001,"库存不足"),
    ;
 
    EmBusinessError(int errCode,String errMsg){
        this.errCode = errCode;
        this.errMsg = errMsg;
    }
 
 
    private int errCode;
    private String errMsg;
 
 
    @Override
    public int getErrCode() {
        return this.errCode;
    }
 
    @Override
    public String getErrMsg() {
        return this.errMsg;
    }
 
    public void setErrCode(int errCode) {
        this.errCode = errCode;
    }
 
    @Override
    public CommonError setErrMsg(String errMsg) {
        this.errMsg = errMsg;
        return this;
    }
}

说明:

在Controller层抛出异常

测试写了具体异常原因

执行进入异常处理内:

执行到枚举异常里:

返回结果:

测试没有明确写异常信息

注意: 异常抛出一定要加@ResponseBody注解,可以把异常序列化为Json格式,如果不添加,将无法抛出异常。。。

还有就是erroCode如果为00001,序列化将会默认去掉前面的0,变成1,所以我们改为10001。

还有就是本节关于通用异常的处理解决了系统异常上的细颗粒度的问题,详见处理通用异常细颗粒度问题,我们这里返回通用异常的时候,可以自己在后面添加上自己写的的异常信息,就可以直接覆盖掉前面的通用异常,当然,学习前面的SpringBoot电商项目里的统一处理异常的细粒度一一列举出来,也是挺不错的。。。

非Cntroller层抛出异常

前面我们实现了在Controller层的异常实现抛出,那我们如果不在controller层的异常抛出该怎么办嘞?

向上面一样抛出异常看看


非controller层使用ExceptionHandler抛出异常

我们不仅service层可能会出问题,mapper层,sql查询也会出问题,有没有什么能够统一处理的嘞?

**这时候就要使用SpringMVC里的ExceptionHandler的处理方法:

Controller层的异常统一处理及返回 - 简书

前面我们学过这种处理方法,参考Spring Boot电商项目用户模块注册接口开发之全局统一处理异常

记得回去复习,前面讲的很细了!!!

package com.imooc.miaoshaproject.controller;
 
import java.util.HashMap;
import java.util.Map;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.NoHandlerFoundException;
 
import com.imooc.miaoshaproject.error.BusinessException;
import com.imooc.miaoshaproject.error.EmBusinessError;
import com.imooc.miaoshaproject.response.CommonReturnType;
 
/**
 * Created by hzllb on 2018/12/22. */@ControllerAdvice
public class GlobalExceptionHandler{
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public CommonReturnType doError(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Exception ex) {
        ex.printStackTrace();
        Map<String,Object> responseData = new HashMap<>();
        if( ex instanceof BusinessException){
            BusinessException businessException = (BusinessException)ex;
            responseData.put("errCode",businessException.getErrCode());
            responseData.put("errMsg",businessException.getErrMsg());
        }else if(ex instanceof ServletRequestBindingException){
            responseData.put("errCode",EmBusinessError.UNKNOWN_ERROR.getErrCode());
            responseData.put("errMsg","url绑定路由问题");
        }else if(ex instanceof NoHandlerFoundException){
            responseData.put("errCode",EmBusinessError.UNKNOWN_ERROR.getErrCode());
            responseData.put("errMsg","没有找到对应的访问路径");
        }else{
            responseData.put("errCode", EmBusinessError.UNKNOWN_ERROR.getErrCode());
            responseData.put("errMsg",EmBusinessError.UNKNOWN_ERROR.getErrMsg());
        }
        return CommonReturnType.create(responseData,"fail");
    }
}

说明:

关于instanceof的用法参考Java面向对象(四)

测试,再次访问

总结

我们异常分为controller层异常,和非controller层异常,以为我们异常都是要抛出到controller层呈现给前端或者用户的。。。

我们异常内亦可以分为通用的异常和自定义的异常,因为我们不可能将每个可能出现的问题都能预料到,但是我们需要尽可能的考虑到,所以我们添加了通用异常,异常不仅出现在代码块中,网络问题也有很多,我们只能统一处理为通用异常,重要的异常我们进行抛出能够有效增强代码维护,增强用户感知与交互,这就是代码的健壮性要求!