什么是异常

异常指的是在程序运行过程中发生的异常事件,通常是由外部问题(如硬件错误、输入错误)所导致的。在Java等面向对象的编程语言中异常属于对象

java 中的异常

java中Exception是所有异常的父类,
在运行时发生的异常叫运行时异常用RuntimeException类表示
运行时异常就是需要我们在程序中捕获并且处理的异常
好的异常处理能帮助我们更好的定位错误发生的原因

异常处理流程

springboot filer抛异常HandlerExceptionResolver spring boot 异常_java


1、在服务层抛出自定义异常类型及不可预知异常类型。

上图中BusinessException为系统的自定义异常类型,程序中在代码显示抛出该异常,此类异常是程序员可预知 的。另一部分是系统无法预知的异常,如:数据库无法连接,服务器宕机等场景下所抛出的异常,此类异常是程序员无 法预知的异常。

2、应用层接收到服务层抛出异常继续向上抛出,应用层自己也可以抛出自定义异常类型及不可预知异常类型。
3、统一异常处理器捕获到异常进行解析。 判断如果为自定义异常则直接取出错误代码及错误信息,因为程序员在抛出自定义异常时已将错误代码和异常信息 指定。 如果为不可预知的异常则统一定义为99999异常代码。
4、统一异常处理器将异常信息格式为前端要求的格式响应给前端。 服务端统一将异常信息封装在下边的Json格式中返回:

{
"errCode": "000000",
"errMessage": "错误说明" 
}

大部分springboot项目异常处理都适用此流程
注:这里的99999异常代码不强制使用该代码,可以自定义,流程上的所有异常代码都可以自定义,但是还是建议按照http协议来指定,比如200是成功,自定义的代码前端如果使用框架那就很可能会认为这是错误的,即使是对的!

springboot自定义异常处理

使用到了lombok,需要在项目中引入lombok依赖

自定义业务异常类
public class BusinessException extends RuntimeException {

	
	private static final long serialVersionUID = 5565760508056698922L;
	
	private ErrorCode errorCode;

	public BusinessException(ErrorCode errorCode) {
		super();
		this.errorCode = errorCode;
	}
	
	public BusinessException() {
		super();
	}

	public BusinessException(String arg0, Throwable arg1, boolean arg2, boolean arg3) {
		super(arg0, arg1, arg2, arg3);
	}
	
	public BusinessException(ErrorCode errorCode, String arg0, Throwable arg1, boolean arg2, boolean arg3) {
		super(arg0, arg1, arg2, arg3);
		this.errorCode = errorCode;
	}

	public BusinessException(String arg0, Throwable arg1) {
		super(arg0, arg1);
	}
	
	public BusinessException(ErrorCode errorCode, String arg0, Throwable arg1) {
		super(arg0, arg1);
		this.errorCode = errorCode;
	}

	public BusinessException(String arg0) {
		super(arg0);
	}
	
	public BusinessException(ErrorCode errorCode, String arg0) {
		super(arg0);
		this.errorCode = errorCode;
	}

	public BusinessException(Throwable arg0) {
		super(arg0);
	}
	
	public BusinessException(ErrorCode errorCode, Throwable arg0) {
		super(arg0);
		this.errorCode = errorCode;
	}

	public ErrorCode getErrorCode() {
		return errorCode;
	}

	public void setErrorCode(ErrorCode errorCode) {
		this.errorCode = errorCode;
	}
	
}
自定义业务异常处理器
@Data
public class RestErrorResponse {
    private String errCode;
    private String errMessage;

    public RestErrorResponse(String errCode, String errMessage) {
        this.errCode = errCode;
        this.errMessage = errMessage;
    }
}
定义全局异常处理器

全局异常处理器使用ControllerAdvice注解实现,ControllerAdvice是SpringMVC3.2提供的注解,用 ControllerAdvice可以方便实现对Controller面向切面编程
ControllerAdvice和ExceptionHandler注解实现全局异常处理

@ControllerAdvice
public class GlobalExceptionHandler {

    private static final Logger LOGGER = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    //捕获异常
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)//返回500状态码
    public RestErrorResponse processExcetion(HttpServletRequest request, HttpServletResponse response, Exception e){
        //异常处理
        //系统自定义异常取出errCode和errMessage
        if (e instanceof BusinessException){
            //控制台打印
            LOGGER.info(e.getMessage(),e);
            //解析系统自定义异常
            BusinessException businessException = (BusinessException) e;
            ErrorCode errorCode = businessException.getErrorCode();
            //错误代码
            int code = errorCode.getCode();
            //错误信息
            String desc = errorCode.getDesc();
            return new RestErrorResponse(String.valueOf(code),desc);
        }
        //非自定义异常类型,定义为99999系统未知错误
        LOGGER.error("系统异常:",e);
        return new RestErrorResponse(String.valueOf(CommonErrorCode.UNKNOWN.getCode()),CommonErrorCode.UNKNOWN.getDesc());
    }
}
定义异常编码类

新建错误接口ErrorCode

public interface ErrorCode {

    int getCode();

    String getDesc();

}

枚举类型的异常编码类实现ErrorCode接口

/**
 * 异常编码
 */
public enum CommonErrorCode implements ErrorCode {

	公用异常编码 //
	E_100101(100101,"传入参数与接口不匹配"),
	E_100102(100102,"验证码错误"),
	E_100103(100103,"验证码为空"),
	E_100104(100104,"查询结果为空"),
	E_100105(100105,"ID格式不正确或超出Long存储范围"),
	E_100106(100106,"上传错误"),
	E_100107(100107,"发送验证码错误"),
	E_100108(100108,"传入对象为空"),
	E_100109(100109,"手机号格式不正确"),
	E_100110(100110,"用户名为空"),
	E_100111(100111,"密码为空"),
	E_100112(100112,"手机号为空"),
	E_100113(100113,"手机号已存在"),
	E_100114(100114,"用户名已存在"),
	E_100115(100115,"密码不正确"),


	E_NO_AUTHORITY(999997,"没有访问权限"),
	CUSTOM(999998,"自定义异常"),
	/**
	 * 未知错误
	 */
	UNKNOWN(999999,"未知错误");


	private int code;
	private String desc;

	public int getCode() {
		return code;
	}

	public String getDesc() {
		return desc;
	}

	private CommonErrorCode(int code, String desc) {
		this.code = code;
		this.desc = desc;
	}


	public static CommonErrorCode setErrorCode(int code) {
       for (CommonErrorCode errorCode : CommonErrorCode.values()) {
           if (errorCode.getCode()==code) {
               return errorCode;
           }
       }
	       return null;
	}
}

注:异常代码应该根据业务需要自定义

异常处理使用

在需要抛出异常的地方throw即可

try {
          //......
        }catch (Exception e){
           //......
           //抛出自定义异常
            throw new BusinessException(CommonErrorCode.E_100102);
        }