在开发软件系统过程中,异常信息是常见的,如何处理系统内部异常,快速定位BUG,是非常考验一位软件开发人员的功底。在软件系统开发过程中,统一自定义异常信息,统一对异常进行捕获处理,这样做能提高软件开发效率,并且使代码看起来更优雅。
一、JAVA中的异常
在Java语言中关于异常的类图如下:
(一)error
是指程序无法处理的错误,表示应用程序运行时出现的重大错误。
例如jvm运行时出现的OutOfMemoryError以及Socket编程时出现的端口占用等程序无法处理的错误
(二)Exception
- 运行时异常:即RuntimeException及其之类的异常。这类异常在代码编写的时候不会被编译器所检测出来,是可以不需要被捕获,但是程序员也可以根据需要进行捕获抛出。常见的RUNtimeException有:NullpointException(空指针异常),ClassCastException(类型转换异常),IndexOutOfBoundsException(数组越界异常)等。
- 编译异常:RuntimeException以外的异常。这类异常在编译时编译器会提示需要捕获,使用try......catch进行处理或者throw 到上层,如果不进行捕获则编译错误。常见编译异常有:IOException(流传输异常),SQLException(数据库操作异常)等。
- java处理异常的机制:抛出异常以及捕获异常 ,一个方法所能捕捉的异常,一定是Java代码在某处所抛出的异常。简单地说,异常总是先被抛出,后被捕捉的
二、spring全局处理异常
(一)自定义异常
/*** @description: 自定义异常类*/publicclassBizExceptionextendsRuntimeException{ privatestaticfinallongserialVersionUID=1L; /*** 错误码*/protectedStringerrorCode; /*** 错误信息*/protectedStringerrorMsg; publicBizException() { super(); } publicBizException(BaseErrorInfoInterfaceerrorInfoInterface) { super(errorInfoInterface.getResultCode()); this.errorCode=errorInfoInterface.getResultCode(); this.errorMsg=errorInfoInterface.getResultMsg(); } publicBizException(BaseErrorInfoInterfaceerrorInfoInterface, Throwablecause) { super(errorInfoInterface.getResultCode(), cause); this.errorCode=errorInfoInterface.getResultCode(); this.errorMsg=errorInfoInterface.getResultMsg(); } publicBizException(StringerrorMsg) { super(errorMsg); this.errorMsg=errorMsg; } publicBizException(StringerrorCode, StringerrorMsg) { super(errorCode); this.errorCode=errorCode; this.errorMsg=errorMsg; } publicBizException(StringerrorCode, StringerrorMsg, Throwablecause) { super(errorCode, cause); this.errorCode=errorCode; this.errorMsg=errorMsg; } publicStringgetErrorCode() { returnerrorCode; } publicvoidsetErrorCode(StringerrorCode) { this.errorCode=errorCode; } publicStringgetErrorMsg() { returnerrorMsg; } publicvoidsetErrorMsg(StringerrorMsg) { this.errorMsg=errorMsg; } publicThrowablefillInStackTrace() { returnthis; } }
(二)统一的返回对象
publicclassResultResponse<T> { /*** 响应代码*/privateStringcode; /*** 响应消息*/privateStringmessage; /*** 响应结果*/privateTdata; publicResultResponse() { } publicResultResponse(BaseErrorInfoInterfaceerrorInfo) { this.code=errorInfo.getResultCode(); this.message=errorInfo.getResultMsg(); } publicStringgetCode() { returncode; } publicvoidsetCode(Stringcode) { this.code=code; } publicStringgetMessage() { returnmessage; } publicvoidsetMessage(Stringmessage) { this.message=message; } publicTgetResult() { returndata; } publicvoidsetData(Tresult) { this.data=result; } /*** 成功** @return*/publicstaticResultResponsesuccess() { returnsuccess(null); } /*** 成功* @param data* @return*/publicstaticResultResponsesuccess(Tdata) { ResultResponserb=newResultResponse(); rb.setCode(ExceptionEnum.SUCCESS.getResultCode()); rb.setMessage(ExceptionEnum.SUCCESS.getResultMsg()); rb.setData(data); returnrb; } /*** 失败*/publicstaticResultResponseerror(BaseErrorInfoInterfaceerrorInfo) { ResultResponserb=newResultResponse(); rb.setCode(errorInfo.getResultCode()); rb.setMessage(errorInfo.getResultMsg()); rb.setData(null); returnrb; } /*** 失败*/publicstaticResultResponseerror(Stringcode, Stringmessage) { ResultResponserb=newResultResponse(); rb.setCode(code); rb.setMessage(message); rb.setData(null); returnrb; } /*** 失败*/publicstaticResultResponseerror( Stringmessage) { ResultResponserb=newResultResponse(); rb.setCode("-1"); rb.setMessage(message); rb.setData(null); returnrb; } publicStringtoString() { returnJSONObject.toJSONString(this); } }
(三)定义基础接口
publicinterfaceBaseErrorInfoInterface { /*** 错误码* @return*/StringgetResultCode(); /*** 错误描述* @return*/StringgetResultMsg(); }
(四)定义枚举类
/*** @description: 异常处理枚举类*/publicenumExceptionEnumimplementsBaseErrorInfoInterface{ // 数据操作错误定义SUCCESS("200", "成功!"), BODY_NOT_MATCH("400","请求的数据格式不符!"), RES_NOT_FOUND("404", "未找到该资源!"), INTERNAL_SERVER_ERROR("500", "服务器内部错误!"), /*** 错误码*/privatefinalStringresultCode; /*** 错误描述*/privatefinalStringresultMsg; ExceptionEnum(StringresultCode, StringresultMsg) { this.resultCode=resultCode; this.resultMsg=resultMsg; } publicStringgetResultCode() { returnresultCode; } publicStringgetResultMsg() { returnresultMsg; } }
(五)自定义全局异常处理
在异常处理类上使用@RestControllerAdvice注解,表明此类是springBoot的全局异常处理类,所有的异常都有此类进行处理,并返回异常信息。
/*** @description: 自定义异常处理*/publicclassGlobalExceptionHandler { privatestaticfinalLoggerlogger=LoggerFactory.getLogger(GlobalExceptionHandler.class); /*** 处理自定义的业务异常* @param req* @param e* @return*/value=BizException.class) (publicResultResponsebizExceptionHandler(HttpServletRequestreq, BizExceptione){ logger.error("发生业务异常!原因是:{}",e.getErrorMsg()); returnResultResponse.error(e.getErrorCode(),e.getErrorMsg()); } /*** 处理其他异常* @param req* @param e* @return*/value=Exception.class) (publicResultResponseexceptionHandler(HttpServletRequestreq, Exceptione){ logger.error("未知异常!原因是:",e); returnResultResponse.error(ExceptionEnum.INTERNAL_SERVER_ERROR); } }
三、总结
合理的异常处理,能够减少代码的重复度和复杂度,有利于代码的阅读及后期维护,并且能够快速定位到BUG,大大提高业务代码的开发效率。