什么是异常
异常指的是在程序运行过程中发生的异常事件,通常是由外部问题(如硬件错误、输入错误)所导致的。在Java等面向对象的编程语言中异常属于对象
java 中的异常
java中Exception是所有异常的父类,
在运行时发生的异常叫运行时异常用RuntimeException类表示
运行时异常就是需要我们在程序中捕获并且处理的异常
好的异常处理能帮助我们更好的定位错误发生的原因
异常处理流程
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);
}