💁 作者:小瓦匠
💖 欢迎关注我的个人公众号:小瓦匠学编程。微信号:xiaowajiangxbc
错误码的制定原则:快速溯源、沟通标准化。 – 阿里巴巴《Java 开发手册》
前言
在项目开发中,你有没有吃过错误码定义混乱的亏,比如:错误码定义无标准,导致无序扩张;错误码语义表述不清晰;错误定位不精准等问题。
在团队开发中,如果能够制定一套合理科学的错误码规约,就可以有效地避免这些问题,从而降低沟通成本以及程序的维护成本。
需求说明
设计错误码规约前,首先要弄清我们的需求:
- 让客户端能够感知到 HTTP 请求是否成功,以便客户端决定下一步该如何处理。
- 错误返回时需要携带错误码和出错信息,可以让开发者通过错误码快速定位问题原因。
错误码设计建议
错误码主要是为了体现业务系统的报错位置及原因,因此在设计时需要给它赋予一定的业务属性。
谁的错?错在哪?
程序开发人员拿到错误码后,必须能够快速知晓错误来源,判断是谁的问题。这也就要求我们设计的错误码首先要具有一定的识别度,方便记忆和对比,并且要有利于团队快速对错误原因达到一致认知。
内容格式统一
错误码应该是统一长度,且内容格式也应该固定的,而不应该是随机编码产生的。其内容可以是一个整数,也可以是一个字符串,但它必须是错误的唯一标识。
通过研究对比各个平台的错误码,我总结出了一个比较实用的错误码设计方案:使用字符数字组合表示,一共有4段组成,不同段表示不同含义。
合理的内容格式,更便于错误码的管理和使用,一方面我们可以根据业务需求有规则的自行扩展;另一方面通过错误码能够精准地定位到具体是哪里出现的什么错误。
错误语义信息
错误码之外的业务独特信息应由 message 来承载,而不是让错误码本身涵盖过多的具体业务属性。通常在请求出现错误时,我们需要返回的错误描述一般包括:错误码,错误说明以及参考文档(可选)
需要注意的是,错误说明是展示给用户的,最好直接告诉用户“该怎么做”而不是“哪里错了”,并且错误说明中不应该包含敏感信息(例如:堆栈信息)。但是为了方便问题排查,我们可以在系统内部日志中打印详细的错误堆栈信息。
合理使用 HTTP 状态码
当请求出错时,应该合理的返回 HTTP 状态码,以便让客户端感知到 HTTP 是否请求成功。为了更清晰的表述和区分状态码的含义,我们将 HTTP 状态码分成如下5类:
常用 HTTP 状态码
HTTP 状态码有很多,但是在错误码设计时,我们只需要重点关注下面这些状态码:
- 200 - 表示请求成功执行
- 400 - 表示客户端出问题
- 401 - 表示认证失败
- 403 - 表示授权失败
- 404 - 表示资源找不到
- 405 - 客户端请求中的方法被禁止
- 500 - 表示服务端出问题
在项目开发中,我们需要根据实际情况,灵活控制状态码的使用,让客户端的处理更容易。
综上所述,一个合理的错误返回应该包含 HTTP 状态码和错误码,并且错误码需要对外暴露错误说明,最好还要支持返回参考文档。例如:
HTTP/1.1 405
Content-Type: application/json
Transfer-Encoding: chunked
Date: Thu, 28 Apr 2022 09:55:54 GMT
Keep-Alive: timeout=60
Connection: keep-alive
{"code":"U00N03", "msg":"HTTP请求方式不受支持"}
错误码的具体实现
在系统开发中,推荐使用枚举类,来存放所有错误码、错误说明等信息。比如以系统公共错误码为例:
// 在下面的代码中只给出了部分有代表性的错误码
@Getter
@AllArgsConstructor
public enum CommonErrorEnum implements IResponseEnum {
/**
* 成功
*/
SUCCESS("000000", 200, "SUCCESS"),
/**
* 参数校验(Valid)异常
*/
PARAM_VALID_ERROR("U00P01", 400, "参数校验异常"),
/**
* Token已过期
*/
TOKEN_EXPIRED("U00A02", 401, "Token已过期"),
/**
* 未授权,不能访问
*/
AUTH_INVALID("U00A05", 403, "未授权,不能访问"),
/**
* 服务器繁忙,请稍后重试
*/
SERVER_BUSY("U00S00", 500,"服务器繁忙"),
/**
* 未知异常,无法识别的异常
*/
SERVER_ERROR("U00O99", 500, "未知异常"),
/**
* Servlet请求类异常(部分)
*/
NoHandlerFoundException("U00N02", 404, "资源找不到"),
HttpRequestMethodNotSupportedException("U00N03", 405, "HTTP请求方式不受支持"),
HttpMediaTypeNotSupportedException("U00N05", 415, "HTTP请求头的 Content-Type 不受支持"),
;
/**
* 返回码
*/
private String code;
/**
* 状态码
*/
private Integer http;
/**
* 返回消息
*/
private String message;
// /**
// * 参考文档 (可选)
// */
// private String reference;
}
总结
总的来说,制定一套错误码规约还是相对容易的,难的是在长期的实践中如何管理并正确使用错误码,保证不被滥用,其复杂程度跟项目规模相匹配。
所以我建议在规约设计时,应该以服务业务为导向,避免过度设计,保持简洁;在管理使用时,应该以先到先得的原则统一审批生效,生效后永久固定。
以上就是我对于错误码规约制定一些想法,规则的制定是灵活的,可变通的,同样也没有绝对的好与坏,只要可以满足你的业务需求就是好的,优秀的。
本人能力有限,各位勉强一观,若能抛砖引玉,不失为一件幸事。
📌 学习
积累
沉淀
分享
💖 欢迎关注我的个人公众号:小瓦匠学编程! 微信号:xiaowajiangxbc
🔎 扫描二维码或微信搜索 “小瓦匠学编程” 即可关注。
(本文完)