现在有个项目,遇到错误代码和异常处理方面的问题,请教各位高手。
背景:项目对外提供服务,这些服务是对很多外部系统提供服务的封装,每个外部系统有自己的错误代码,没有统一的规范。有些外部系统自己规范都不统一,有的时候返回错误代码,有的时候返回错误信息,有的时候错误代码和错误信息在一起。
目前可选的解决方案:
一、直接使用外系统错误代码
方法:直接使用外系统错误代码
问题:混乱,错误代码可能重复,排除该方法
二、使用统一的错误代码
方法:对外部系统的错误代码重新编排,按照模块进行分类,没有错误代码的错误当做未知错误。
问题:需要维护一个错误代码列表及映射关系,对于外部系统错误不规范的情况,需要有专门的代码进行处理
三、使用异常,统一当做checked exception处理
方法:继承Exception
问题:不符合异常处理最佳实践,有些应该是RuntimeException的也被强制要求捕获了
四、使用异常,根据外系统错误类型区分是checked exception还是unchecked exception
方法:根据外部系统类型,区分哪些是程序逻辑问题(继承RuntimeException),哪些是系统问题(继承Exception),映射成不同的异常类型
问题:外系统错误说明可能有误,导致映射到异常时类型不准确
针对这种情况,各位觉得应该使用哪种方式处理比较好,另外,对于异常的类层次结构实践经验不多,只是简单看过Spring的异常类设计,有哪些好的书或资料可以学习一下。
1、如果你这个系统是新系统/或者以后会有更多的子系统依赖 建议还是规范起来
1.1、如果对外提供的是jar包直接抛异常 没关系
1.2、如果走如http/webservice 提供一个异常到错误码的映射(比如直接写到异常里) 这个是标准的 以后的标准
1.3、对于遗留系统 提供一个转换处理器(如spring对jdbc、hibernate等的都转换为DataAccessException)
如果外部系统能改造的话 建议沟通下一起改造下 否则就要他们提供当前系统的错误码 然后联调(可能存在bug 很正常的 所以要全面测试)
1.4、考虑下spring的NestedException 嵌套异常 来存储原始异常
1.5、如果可以放弃checkedException 如web系统都会有一个异常解析器 出错了 会交给他 所以unchecked即可
“简单是最好”,我推荐第二种。
【1】里面可能需要定义两个,业务异常和系统异常。但无论哪种都是RuntimeException。
(是否runtime这个有争论,我个人推荐全部runtime,无须强制捕捉。)
总之,
最后,统一处理所有异常的地方可能需要映射,不同异常对应不同处理方式。
如果没有这种需求,也无须搞映射。能区分即可。
“如无必要,勿增实体”——奥卡姆剃刀定律
像这种类似接口机性质的系统(如:自己提供若干服务,供外部N多个系统调用),肯定需要对错误代码进行统一。目前很多这种类型的项目,如淘宝的TOP、开源rest服务框架ROP等等。
首先自己系统内部要处理各种异常,从database->orm-service-(webservice/rest service/http service……),当然底层的异常需要由上层来捕获。因为上层需要根据异常类型映射到对应的错误代码,再返回到对应的外部系统调用结果。
如果按照各个外部系统的错误码,那你同一个服务供若干外系统调用时,还要根据外系统类型,再返回对应的错误码?那么一个新的系统需要调用已有服务时,那不是要更改接口代码(如果扩展性做的好,就增加外系统对应的错误码配置字典)。但是这样,对后期的维护还是麻烦。
有时候,做接口,不仅仅是技术问题,还要看本系统的重要程度,如果是核心系统,就应该强势起来,不能被外系统牵着鼻子走,因为被外系统牵着鼻子走,到时候核心系统出问题,客户只会怪核心系统设计不好等等……