前言

本文说的自定义异常指的是继承了RuntimeException,专门用于Spring全局异常捕获处理的自定义异常类型,需要应用程序显示捕获并处理的异常不在本次讨论范围内。

本随笔经验总结,如有不足还原留言指正。

场景

使用java提供服务的后端系统,使用者(可能是web前端或者是第三方调用者)通过api形式进行调用。

目的

大多时候实现业务流程时总是可以假设所有操作都是成功的,如果有异常,直接根据异常类型转换为对应的自定义异常从而结束当前逻辑。

根据系统异常类型制定对应的异常,以便进行全局异常处理。

异常一般伴随着对应的错误码,所以需要实现不同类型的异常对应不通类型的错误码,不得混用。

对异常进行分类

系统异常可以大致分为客户端异常和服务端异常,即任何异常都可以转换为这两类异常。

客户端异常:如参数错误等,建议http返回状态码为4xx。

服务端异常:如某些在意料之外并且不属于客户端异常操作引起的异常,建议http返回状态码为5xx。

异常体系设计类图

类/接口说明

AbstractException

AbstractException 表示自定义已知异常,即该异常可以完全不用显示处理,而是可以直接交给全局异常捕获自动处理,其中它有两个子类,一个是ClientException和SystemException,这两个子类分别与上面提到的可能的系统异常想对应。

ClientException

ClientException表示"客户端异常",如接口方法不对或者参数不符合要求等。引发该异常时,除了返回对应的错误码与错误描述外,http响应状态码为4xx(一般为400)。

SystemException

SystemException表示“服务端异常”,如图片下载失败导致我们系统本身出现不可控异常以及系统调用通道发生异常等。引发该异常时,除了返回对应的错误码与错误描述外,http响应状态码为5xx(一般为500)。

ClientErrorCodeMark

创建ClientException异常时所需的错误码抽象,即ClientException异常仅仅接受ClientErrorCodeMark类型的错误码。目的是防止不同类型的错误码混用,即客户端异常错误码不能用于服务端异常。

SystemErrorCodeMark

创建SystemException异常时所需的错误码抽象,即SystemException异常仅仅接受SystemErrorCodeMark类型的错误码。目的是防止不同类型的错误码混用,即客户端异常错误码不能用于服务端异常。

ClientErrorCodeMark.Code

SystemErrorCodeMark.Code

Code分别是ClientErrorCodeMark和SystemErrorCodeMark的实现类,同时也是枚举对象。即在这里定义了各个错误码以及错误码对应的描述信息。

由以上类图可以看出,所有接口或者类都实现了ErrorInfo这个接口,而通过该接口可以拿到异常错误码和错误描述,也就是说,还是像以前一样,一旦引发异常,可以随时中断处理并且能返回给调用方一个合理的错误信息。

具体代码

/*** 公共接口,能获取错误描述和错误码.

*

* Created by DaiWang on 2019/7/23.

*

*

*@authorDaiWang*/

public interfaceErrorInfo {/*** 获取异常对应的错误码.

*

*@return错误码系统定义的错误码*/String getErrorCode();/*** 获取错误码对应的描述信息.

*

* 如果本地对该描述信息进行设置,则本地的优先,否则自动从错误码系统获取错误码对应的描述信息.

*

*@return错误码对应的描述信息*/String getErrorDesc();

}

/*** 自定义全局异常.

*@authorDaiWang*/

public abstract class AbstractException extends RuntimeException implementsErrorInfo {publicAbstractException() {super();

}publicAbstractException(String message) {super(message);

}publicAbstractException(String message, Throwable cause) {super(message, cause);

}publicAbstractException(Throwable cause) {super(cause);

}protected AbstractException(String message, Throwable cause, boolean enableSuppression, booleanwritableStackTrace) {super(message, cause, enableSuppression, writableStackTrace);

}

}

/*** 外部传参数非法等客户端异常.

*

即该异常由调用方导致.如调用通道时用户传递的图片过大等.

*

直接提示用户相关错误即可

*

* Created by DaiWang on 2019/7/23.

*

*

*@authorDaiWang*/

public class ClientException extendsAbstractException {privateErrorInfo errorCode;/*** 本地错误描述信息,其优先级高于{@linkErrorInfo}中的errorDesc,即如果该值不为空,则以该值为准*/@SetterprivateString errorDesc;/***@paramerrorCode 枚举的错误码类型,其中包含了错误码和对应的错误码描述信息.*/

publicClientException(ClientErrorCodeMark errorCode) {super();this.errorCode =errorCode;

}/***@paramerrorCode 枚举的错误码类型,其中包含了错误码和对应的错误码描述信息.

*@parammessage 最好是自定义的详细描述信息,用于打日志,也可以和{@linkErrorInfo#getErrorDesc()}相同*/

publicClientException(ClientErrorCodeMark errorCode, String message) {super(message);this.errorCode =errorCode;

}/***@paramerrorCode 枚举的错误码类型,其中包含了错误码和对应的错误码描述信息.*/

publicClientException(ClientErrorCodeMark errorCode, Throwable cause) {super(cause);this.errorCode =errorCode;

}/***@paramerrorCode 枚举的错误码类型,其中包含了错误码和对应的错误码描述信息.

*@parammessage 最好是自定义的详细描述信息,用于打日志,也可以和{@linkErrorInfo#getErrorDesc()}相同*/

publicClientException(ClientErrorCodeMark errorCode, String message, Throwable cause) {super(message, cause);this.errorCode =errorCode;

}

@OverridepublicString getErrorCode() {returnerrorCode.getErrorCode();

}/*** 获取错误码对应的描述信息.

*

* 如果本地对该描述信息进行设置,则本地的优先,否则自动从错误码系统获取错误码对应的描述信息.

*

*@return错误码对应的描述信息*/@OverridepublicString getErrorDesc() {if (!StringUtils.isEmpty(errorDesc)) {returnerrorDesc;

}returnerrorCode.getErrorDesc();

}

@OverridepublicString getMessage() {

String message= super.getMessage();if(StringUtils.isEmpty(message)) {

message= this.getErrorDesc();

}returnmessage;

}

}

ClientException

/*** 客户端异常标记接口。

* 用于标记{@linkClientException}对象的错误码参数类型,防止错误码串用.

*@authorDaiWang*/

public interface ClientErrorCodeMark extendsErrorInfo {/*** 用户操作异常错误码枚举*/@Getterenum Code implementsClientErrorCodeMark {//region 参数错误

/*** 参数错误(可以笼统的将所有参数错误都包含在内,并重新定义错误描述,一般用于框架参数自定义错误验证)*/PARAMETER_ERROR("错误码1", "参数错误"),//region 操作过于频繁 错误码前缀: BOX_GA12xx

FREQUENTLY("错误码2", "操作过于频繁,请稍候再试"),//endregion//----------------------------------------------

/*** 照片质量校验不合格,请重新拍照后重试*/BOX_GA0051("BOX_GA0051"),

;

Code(String errorCode) {this.errorCode =errorCode;this.errorDesc =AssemblyUtil.getErrorOutDesc(errorCode);

}

Code(String errorCode, String errorDesc) {this.errorCode =errorCode;this.errorDesc =errorDesc;

}/*** 错误码.*/

privateString errorCode;/*** 错误码对应的外部描述信息,该信息是通过错误码自动获取,并且直接返回给调用方.*/

privateString errorDesc;

}/*** 快速构建一个自定义错误描述错误信息对象.

*

* 一般用于相同的错误码,但是不同的错误描述信息(类似).

* 比如常见的参数错误,但是可以使用参数错误的通用错误码在描述中提示调用者更具体的错误描述.

*

*@paramdesc 新的错误描述

*@return使用自定义描述替换原有描述的信息对象副本*/

defaultClientErrorCodeMark as(String desc) {

ErrorInfo errorInfo= this;return newClientErrorCodeMark() {

@OverridepublicString getErrorCode() {returnerrorInfo.getErrorCode();

}

@OverridepublicString getErrorDesc() {returndesc;

}

};

}

}

ClientErrorCodeMark

/*** 转换后的系统异常.

*

* 系统环境异常、数据库连接超时.

*

* 提示用户系统异常,并且需要人工排查.

*

* Created by DaiWang on 2019/7/23.

*

*

*@authorDaiWang*/

public class SystemException extendsAbstractException {privateErrorInfo errorCode;/*** 本地错误描述信息,其优先级高于{@linkErrorInfo}中的errorDesc,即如果该值不为空,则以该值为准*/@SetterprivateString errorDesc;/***@paramerrorCode 枚举的错误码类型,其中包含了错误码和对应的错误码描述信息.*/

publicSystemException(SystemErrorCodeMark errorCode) {super();this.errorCode =errorCode;

}/***@paramerrorCode 枚举的错误码类型,其中包含了错误码和对应的错误码描述信息.

*@parammessage 最好是自定义的详细描述信息,用于打日志,也可以和{@linkErrorInfo#getErrorDesc()}相同*/

publicSystemException(SystemErrorCodeMark errorCode, String message) {super(message);this.errorCode =errorCode;

}/***@paramerrorCode 枚举的错误码类型,其中包含了错误码和对应的错误码描述信息.*/

publicSystemException(SystemErrorCodeMark errorCode, Throwable cause) {super(cause);this.errorCode =errorCode;

}/***@paramerrorCode 枚举的错误码类型,其中包含了错误码和对应的错误码描述信息.

*@parammessage 最好是自定义的详细描述信息,用于打日志,也可以和{@linkErrorInfo#getErrorDesc()}相同*/

publicSystemException(SystemErrorCodeMark errorCode, String message, Throwable cause) {super(message, cause);this.errorCode =errorCode;

}

@OverridepublicString getErrorCode() {returnerrorCode.getErrorCode();

}/*** 获取错误码对应的描述信息.

*

* 如果本地对该描述信息进行设置,则本地的优先,否则自动从错误码系统获取错误码对应的描述信息.

*

*@return错误码对应的描述信息*/@OverridepublicString getErrorDesc() {if (!StringUtils.isEmpty(errorDesc)) {returnerrorDesc;

}returnerrorCode.getErrorDesc();

}

@OverridepublicString getMessage() {

String message= super.getMessage();if(StringUtils.isEmpty(message)) {

message= this.getErrorDesc();

}returnmessage;

}

}

SystemException

/*** 标记接口.

* 用于标记{@linkSystemException}对象的错误码参数类型,防止错误码串用.

*@authorDaiWang*/

public interface SystemErrorCodeMark extendsErrorInfo {/*** 我方系统异常错误码枚举*/@Getter

@AllArgsConstructorenum Code implementsSystemErrorCodeMark {/*** 系统错误(本系统).*/SYSTEM_ERROR_LOCAL("错误码3", "系统异常"),/*** 系统内部错误(其他服务引起的错误,如通道异常)*/SYSTEM_ERROR_OTHER("错误码4", "系统繁忙"),//-----------------------------------------------------------------------------------------------------------------

/*** 系统内部错误*/SYS_0001("错误码5"),/*** API不存在*/SYSTEM_NOT_API("错误码6" , "API不存在"),/*** API不存在*/HTTP_NOT_SUPPORTED("错误码7" , "HTTP请求方法不支持"),

;

Code(String errorCode) {this.errorCode =errorCode;this.errorDesc =AssemblyUtil.getErrorOutDesc(errorCode);

}/*** 错误码.*/

privateString errorCode;/*** 错误码对应的外部描述信息,该信息是通过错误码自动获取,并且直接返回给调用方.*/

privateString errorDesc;

}/*** 快速构建一个自定义错误描述错误信息对象.

*

* 一般用于相同的错误码,但是不同的错误描述信息(类似).

* 比如常见的参数错误,但是可以使用参数错误的通用错误码在描述中提示调用者更具体的错误描述.

*

*@paramdesc 新的错误描述

*@return使用自定义描述替换原有描述的信息对象副本*/

defaultSystemErrorCodeMark as(String desc) {

ErrorInfo errorInfo= this;return newSystemErrorCodeMark() {

@OverridepublicString getErrorCode() {returnerrorInfo.getErrorCode();

}

@OverridepublicString getErrorDesc() {returndesc;

}

};

}

}

SystemErrorCodeMark

boot返回码规范 spring_SpringBoot自定义异常体系和错误码规范定义(个人经验总结)...相关推荐

  1. boot返回码规范 spring_SpringBoot 系列 web 篇之自定义返回 Http Code 的 n 种姿势

    200105-SpringBoot 系列 web 篇之自定义返回 Http Code 的 n 种姿势 虽然 http 的提供了一整套完整.定义明确的状态码,但实际的业务支持中,后端并不总会遵守这套规则 ...

  2. boot返回码规范 spring_springboot项目编码规范

    1.统一返回消息体规范 /** * 用户信息接口 * @return */ @ApiOperation(value = "用户信息接口", notes = "用户信息接口 ...

  3. boot返回码规范 spring_sprigboot-new-coding-standards

    sprigboot-new-coding-standards 介绍 SpringBoot脚手架,遵守严格的代码规范. 规范详细说明 1.遵循标准RESTful API 2.异常采用枚举进行封装(业务内 ...

  4. boot返回码规范 spring_三种自定义SpringBoot返回的状态码

    关于如何自定义SpringBoot返回的状态码 关于HttpStatus 在SpringBoot中关于状态码有一个枚举类型,如下. public enum HttpStatus { CONTINUE( ...

  5. java异常自定义返回信息,Spring Boot 如何自定义返回错误码错误信息

    说明 在实际的开发过程中,很多时候要定义符合自己业务的错误码和错误信息,而不是统一的而不是统一的下面这种格式返回到调用端 INTERNAL_SERVER_ERROR(500, "Intern ...

  6. sql在insert的同时把某个字段返回来_项目实践:后端接口统一规范的同时,如何优雅得扩展规范?...

    推荐学习 春招指南之"性能调优":MySQL+Tomcat+JVM,还怕面试官的轰炸? 这是什么神仙面试宝典?半月看完25大专题,居然斩获阿里P7offer 前言 之前写过如何通过 ...

  7. 关于SP一些响应码的API返回码及解析集合

    在一些金融的行业(银行.证券.保险等),如果接触了一些中间件,比如长城.恒银.广电等一些厂商的设备,不同的厂商有不同的一些规范,在应用开发的过程中难免会和中间件的错误码打交道,这里总结一下.基本常用的 ...

  8. Spring Boot 返回 XML 数据,一分钟搞定!

    2019独角兽企业重金招聘Python工程师标准>>> Spring Boot 返回 XML 数据,前提必须已经搭建了 Spring Boot 项目,所以这一块代码就不贴了,可以点击 ...

  9. Spring Boot源码简析 @EnableTransactionManagement

    相关阅读 Spring Boot源码简析 事务管理 Spring Boot源码简析 @EnableAspectJAutoProxy Spring Boot源码简析 @EnableAsync Sprin ...

最新文章

  1. concurrenthashmap 面试题
  2. Flutter之Decoration(边框、圆角、阴影、形状、渐变、背景图像等)
  3. 【风控建模】互联网金融-机器学习及评分卡构建
  4. BaseExecutor.query()-清空本地缓存
  5. SQL Server索引怎么用
  6. 16.进程间的通信:管道
  7. 《Entity Framework 6 Recipes》中文翻译系列 (42) ------ 第八章 POCO之使用POCO
  8. linux动态时钟探索
  9. 155.最小栈(力扣leetcode) 博主可答疑该问题
  10. Xcode中导入文件报错
  11. Matlab·Simulink的使用—【S函数的创建与应用】
  12. FileNet小错误汇总
  13. 物联网解决方案:智慧物流方案
  14. linux中yum -y install mysql为什么默认是mariadb?以及mysql yum源的配置
  15. 如何看待“英特尔是一家软件公司”?
  16. The Book Thief
  17. 一个简单的SQL注入攻击
  18. p,np,npc,np难问题,确定图灵机与非确定图灵机
  19. 32位与64位操作系统以及CPU的关系
  20. Coredata的版本升级

热门文章

  1. U盘装linux系统,刻录系统光盘
  2. 江沅科技AIEA(人工智能量化交易)开创中国金融智能交易新时代
  3. 乐高无线服务器必须有房主,乐高联手腾讯出游戏,国内首创儿童保护专属服务器...
  4. 异步编程的方式有哪几种?
  5. 设置WPS文档笔记模版
  6. 智能组件和木偶组件_木偶简介
  7. 全球定位系统的50种用途或应用
  8. 计算机及应用自考考研学校,【王道论坛统计】2010 34所自主划线院校计算机复试线及相关详细报考信息(感谢gumuguo)...
  9. C#微信支付(一)—— 基础帮助类
  10. 马克思主义基本原理概论(二)试题