如何定义错误码
好久没有写文章了,搞得不知道写啥,最近遇到了一个问题,决定把东西总结一下,记录下来。
1. 背景
最近开发,发现遇到了一个问题,那就是关于如何定义错误码。写代码写着写着迷糊了,突然发现不知道如何定义错误码,错误码对我们来说,到底有什么用?今天我结合自己的实现,来说一下如何定义错误码
2. 处理错误的方式
在 Spring 时代,spring 提供的 ControllerAdvice,RestControllerAdvice 给我们集中处理异常提供了一种很好的解决方案。我们也经常用这样的方式来解决方案。但是,结合我们一部分常用的也给我带来了一部分烦恼,我来说一下为什么。
2.1 处理方案
在我们自己的代码中,经常会定义一种通用的返回结果,大多数都叫 Result。代码如下:
我们经常会用这个对象当做接口的公共返回,所以理所当然的,在定义公共异常处理逻辑的时候,也会写成如下的样子。代码如下:
这是一个处理公共异常的类,里面也理所当然的返回了 Result 对象,看起来似乎都是天衣无缝,没什么问题,但是,也给我带来了一些困惑。
2.2 我的困惑
当我们遇到异常的时候,会写下如下的代码:
throw new BizException(errorCode, errorMessage);
错误码是我们自己定义的,例如:errorCode=400, errorMsg="session timeout",然后这个异常会理所当然的被我们的公共异常处理器捕获,然后返回给前端一个公共的 Result,前端拿到状态码来处理相应的逻辑,例如:跳转到登录页面。这一切看起来都是正常的,但是,有个但是,如果我们返回的状态码不是 400 的时候呢? 或者有其他的状态码的时候呢?600, 601,602 ,前端都要一一处理吗?这个说实话,看起来怪怪的,处理的要求太多了,前端的改动也太大了。还有一个问题是每个请求都返回的 HttpStatus 都是 200,给测试也带来了一定的烦恼,测试需要认真仔细,一一的看你的接口返回的 内容,来判断你的返回内容是都正确, 这无疑是增加了许多的工作量。看起来状态码似乎也没带来一个好的效果。
2.3 我的思考
就我目前遇到的情况来说,我觉得错误码是一个可有可无的东西,因为我只需要判断 success 是否为 True 就好了,因为当 success 为 false 的时候,都需要抛出 message 来展示。那我是不是可以随意定义错误码了呢?如果想要用上错误码,怎么用最合适,最有价值呢?错误码用来做错误接口提示可以吗?
3. 解开迷惑
对错误码理解少,或者说当错误直接提示 message,或者说想在发生异常的时候,通过链路 id 或者其他方式找异常的我们都太天真了。我顿悟是在一张图上,图上的内容大概如下。
看到这个图的第一反应,我觉得需要定义好多错误码,好麻烦,能不能给出一种公共的,然后让前端好处理一些。并且我想改变我的代码,不想让测试费劲的看哪个接口出问题,便于我自己找问题,也便于测试。而且我还想前端基于目前的代码,不要有太大的改动,就算有改动,没覆盖到的地方,在以后的迭代中进行修改。
思前想后,想到一个这样的处理逻辑,一下子处理的当前的困境。
3.1 如何定义错误码
想来想去,觉得这样的定义错误码蛮合适的,给人一种靠谱的感觉。
错误码公式:系统编码 + 业务编码 + 错误码 + 接口编码
3.1.1 系统编码
系统编码:系统编码就是对每个系统进行编码,如有三个系统 A,B,C,然后我进行了编号,分别为: 01,02,03,通过这几个数字,我就可以找到对应的系统。
3.1.2 业务编码
业务编码:业务编码就是对应具体的业务,如:我的系统中涉及到了 D,E,F 三个业务,然后我对三个业务也进行了编码,分别是 100,200,300,通过这几个数字,我也可以找对对应的业务。
3.1.3 错误码
错误码就是要根据具体的情况来了,如下。
这些就要根据具体的情况,来定义一些编码,便于知道当出现这些异常的时候,需要如果做处理。
3.1.4 接口编码
接口编码,就是对每个接口进行编码,如:D 业务的接口有:m,n 两个接口。定义一个接口编码如下:
通过对具体的接口进行错误码定义,就可以通过错误码找到对应的接口。
3.2 如果使用错误码
我们光定义好了错误码还是没有太大作用的,当生产环境出现问题的时候,不方便我们第一时间找出出现问题的地方,所以我们需要前端配合起来将错误码展示出来。
如何展示呢? 其实很简单,就是通过在 msg 后边,把错误代码括号起来。给一个 demo:系统繁忙,请稍后再试(000160012)
,我们通过前端展示的错误码000160012
就可以知道出现的问题是:00 号系统,01 号业务,600(系统异常,是兜底,还是放过),01 号业务的 12 号接口,这样,我们就可以快速定位到具体的代码中去,在配合日志,很快就可以揪出 bug 出现的地方,是不是很方便?
哈哈, 不知道大家发现一个问题没? 这样虽然解决了快速定位接口错误的问题,但是没有给测试带来收益,因为目前来说,接口的返回状态都是 200,这样就无法区分出哪一个接口是具体的错误,所以我们还要针对这一种情况进行处理。处理的代码如下:
我这个处理业务的方法,先说一下为什么要这么做。
因为是业务异常,是我们自己抛的,所以不用打印多余的堆栈日志。
处理登录超时,可以给出 HttpStatus=401,让前端请求一目了然,可以针对 HttpStatus 做出具体处理
当系统异常的时候,需要把此次请求 HttpStatus=500,前端一目了然。
通过返回ResponseEntity
而不是简单的Result
,就解决了测试困难的情况。 不要通过固定思维,返回 Result,局限了自己,致使每次返回的 HttpStatus = 200, 使测试情况复杂化。
4. 总结
这一次,自己通过总结,算是理解了错误码的具体用法,分享出来,有问题,欢迎大家讨论呀!
版权声明: 本文为 InfoQ 作者【编号94530】的原创文章。
原文链接:【http://xie.infoq.cn/article/ad94a95cf20985d31b1e78d60】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论