一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第18天,点击查看活动详情。
在开发软件系统过程中,异常信息是常见的,如何处理系统内部异常,快速定位BUG,是非常考验一位软件开发人员的功底。在软件系统开发过程中,统一自定义异常信息,统一对异常进行捕获处理,这样做能提高软件开发效率,并且使代码看起来更优雅。
一、JAVA中的异常
在Java语言中关于异常的类图如下:
(一)error
是指程序无法处理的错误,表示应用程序运行时出现的重大错误。
例如jvm运行时出现的OutOfMemoryError以及Socket编程时出现的端口占用等程序无法处理的错误
(二)Exception
- 运行时异常:即RuntimeException及其之类的异常。这类异常在代码编写的时候不会被编译器所检测出来,是可以不需要被捕获,但是程序员也可以根据需要进行捕获抛出。常见的RUNtimeException有:NullpointException(空指针异常),ClassCastException(类型转换异常),IndexOutOfBoundsException(数组越界异常)等。
- 编译异常:RuntimeException以外的异常。这类异常在编译时编译器会提示需要捕获,使用try......catch进行处理或者throw 到上层,如果不进行捕获则编译错误。常见编译异常有:IOException(流传输异常),SQLException(数据库操作异常)等。
- java处理异常的机制:抛出异常以及捕获异常 ,一个方法所能捕捉的异常,一定是Java代码在某处所抛出的异常。简单地说,异常总是先被抛出,后被捕捉的
二、spring全局处理异常
(一)自定义异常
/**
* @description: 自定义异常类
*/
public class BizException extends RuntimeException{
private static final long serialVersionUID = 1L;
/**
* 错误码
*/
protected String errorCode;
/**
* 错误信息
*/
protected String errorMsg;
public BizException() {
super();
}
public BizException(BaseErrorInfoInterface errorInfoInterface) {
super(errorInfoInterface.getResultCode());
this.errorCode = errorInfoInterface.getResultCode();
this.errorMsg = errorInfoInterface.getResultMsg();
}
public BizException(BaseErrorInfoInterface errorInfoInterface, Throwable cause) {
super(errorInfoInterface.getResultCode(), cause);
this.errorCode = errorInfoInterface.getResultCode();
this.errorMsg = errorInfoInterface.getResultMsg();
}
public BizException(String errorMsg) {
super(errorMsg);
this.errorMsg = errorMsg;
}
public BizException(String errorCode, String errorMsg) {
super(errorCode);
this.errorCode = errorCode;
this.errorMsg = errorMsg;
}
public BizException(String errorCode, String errorMsg, Throwable cause) {
super(errorCode, cause);
this.errorCode = errorCode;
this.errorMsg = errorMsg;
}
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
public String getErrorMsg() {
return errorMsg;
}
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
@Override
public Throwable fillInStackTrace() {
return this;
}
}
(二)统一的返回对象
public class ResultResponse<T> {
/**
* 响应代码
*/
private String code;
/**
* 响应消息
*/
private String message;
/**
* 响应结果
*/
private T data;
public ResultResponse() {
}
public ResultResponse(BaseErrorInfoInterface errorInfo) {
this.code = errorInfo.getResultCode();
this.message = errorInfo.getResultMsg();
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getResult() {
return data;
}
public void setData(T result) {
this.data = result;
}
/**
* 成功
*
* @return
*/
public static ResultResponse success() {
return success(null);
}
/**
* 成功
* @param data
* @return
*/
public static ResultResponse success(T data) {
ResultResponse rb = new ResultResponse();
rb.setCode(ExceptionEnum.SUCCESS.getResultCode());
rb.setMessage(ExceptionEnum.SUCCESS.getResultMsg());
rb.setData(data);
return rb;
}
/**
* 失败
*/
public static ResultResponse error(BaseErrorInfoInterface errorInfo) {
ResultResponse rb = new ResultResponse();
rb.setCode(errorInfo.getResultCode());
rb.setMessage(errorInfo.getResultMsg());
rb.setData(null);
return rb;
}
/**
* 失败
*/
public static ResultResponse error(String code, String message) {
ResultResponse rb = new ResultResponse();
rb.setCode(code);
rb.setMessage(message);
rb.setData(null);
return rb;
}
/**
* 失败
*/
public static ResultResponse error( String message) {
ResultResponse rb = new ResultResponse();
rb.setCode("-1");
rb.setMessage(message);
rb.setData(null);
return rb;
}
@Override
public String toString() {
return JSONObject.toJSONString(this);
}
}
(三)定义基础接口
public interface BaseErrorInfoInterface {
/**
* 错误码
* @return
*/
String getResultCode();
/**
* 错误描述
* @return
*/
String getResultMsg();
}
(四)定义枚举类
/**
* @description: 异常处理枚举类
*/
public enum ExceptionEnum implements BaseErrorInfoInterface{
// 数据操作错误定义
SUCCESS("200", "成功!"),
BODY_NOT_MATCH("400","请求的数据格式不符!"),
RES_NOT_FOUND("404", "未找到该资源!"),
INTERNAL_SERVER_ERROR("500", "服务器内部错误!"),
/**
* 错误码
*/
private final String resultCode;
/**
* 错误描述
*/
private final String resultMsg;
ExceptionEnum(String resultCode, String resultMsg) {
this.resultCode = resultCode;
this.resultMsg = resultMsg;
}
@Override
public String getResultCode() {
return resultCode;
}
@Override
public String getResultMsg() {
return resultMsg;
}
}
(五)自定义全局异常处理
在异常处理类上使用@RestControllerAdvice注解,表明此类是springBoot的全局异常处理类,所有的异常都有此类进行处理,并返回异常信息。
/**
* @description: 自定义异常处理
*/
@RestControllerAdvice
public class GlobalExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
/**
* 处理自定义的业务异常
* @param req
* @param e
* @return
*/
@ExceptionHandler(value = BizException.class)
public ResultResponse bizExceptionHandler(HttpServletRequest req, BizException e){
logger.error("发生业务异常!原因是:{}",e.getErrorMsg());
return ResultResponse.error(e.getErrorCode(),e.getErrorMsg());
}
/**
* 处理其他异常
* @param req
* @param e
* @return
*/
@ExceptionHandler(value =Exception.class)
public ResultResponse exceptionHandler(HttpServletRequest req, Exception e){
logger.error("未知异常!原因是:",e);
return ResultResponse.error(ExceptionEnum.INTERNAL_SERVER_ERROR);
}
}
三、总结
合理的异常处理,能够减少代码的重复度和复杂度,有利于代码的阅读及后期维护,并且能够快速定位到BUG,大大提高业务代码的开发效率。