Springboot项目错误码的设计与实现
HTTP状态码和我们平时的错误码不同,状态码太少了,无法满足我们业务中的需求。
然而,所有请求都返回200,然后数据体里包含错误码的方式,又抛弃了HTTP状态码,抛弃了普遍共识。
本来应该遵照HTTP协议的约定,根据HTTP状态码设计返回体。然而,很多电信营业商会拦截非200响应。
采用 {error} or {result} 的形式:
程序遇到错误时,前端返回错误码和错误信息。正常时,直接返回期望的结果。
这种方法是作死,增加了复杂性!
所以推荐的做法是采用{error,result} 的形式:
正常响应和错误都放在body体里
一、返回格式
正常访问服务器时,返回200的HTTP状态码,然后内部描述正常或错误信息
{"errcode":"A2001","errmsg":"access_token expired","data":{"userid": "zhangsan","name": "张三","department": [1, 2],"open_userid": "xxxxxx"}
}
二、错误码的设计
好的错误码解决的基本问题是“谁的错?”。
更高的要求是
(1)易于记忆和比对(Equals)。
(2)脱离文档和系统平台达到线下轻量化地自由沟通的目的。
(一)设计原则
根据《阿里巴巴开发手册》建议,错误码的制定需
- 快速溯源,沟通标准化
- 不体现版本号和错误等级
- 全部正常时,返回00000
- 为字符串类型,共5位(产生来源,四位数字编号)
- 不得与公司业务和组织架构挂钩,应该自增数字
- 因为国际化i18n,不要用枚举定义错误码
- 不能直接输出给用户作为提示信息使用,不要替代错误信息(errorMessage)
- 错误码可分为一二三级宏观错误,跟HTTP状态码没有关系
1.为什么不能用纯数字错误码?
因为数字错误码,不便于感性记忆和分类,不容易记住。
在日志中无法确定某串数字是否是错误码,还是某个数值。
2.为什么不能用纯字母错误码?
纯字母错误码不便于排序,用英语不能准确描述错误。
3.错误码的输出路径有哪些?
分为两类:
3.1面向日志输出
- 服务或域内传递,最终是输出到日志。
3.2面向外部传递(常用)
- 域内向域外
- 服务端传递到前端
- OpenAPI 错误码
- 内部不同域之间
4.输出到日志和输出到外部的错误码有什么区别?
按照《手册》的建议设计出的面向日志的错误码定义共十三位(十位有意义,三位连接符),并且应该具有如下分类:
- 应用标识,表示错误属于哪个应用,三位数字。
- 功能域标识,表示错误属于应用中的哪个功能模块,三位数字。
- 错误类型,表示错误属于那种类型,一位字母。
- 错误编码,错误类型下的具体错误,三位数字。
《手册》还有一条是规定错误码应该如何定义:
错误码为字符串类型,共 5 位,分成两个部分:错误产生来源+四位数字编号。
五位错误码的好处是易记,但是对于面向日志的错误码场景利用错误码制作需要分类的业务监控大盘将变得比较困难,比如统计应用 A 的功能 B 的错误出现次数。
同样在系统间传递这个类型的错误码非常有可能发生错误码冲突。
当然对于分为四段的错误码同样尤其不好的一面,应用标识和功能域标识需要有专人去管理或者开发一个错误码管理工具,否则时间一长很容易产生定义的混乱形成破窗。
因此,五位错误码适合传递到外部。
5.面向外部传递的错误码如何分工协作?
域外系统通过错误码进行后续的动作,或是中断操作,或是记录日志继续执行。
前端通过错误码,给出用户准确的错误提示或者忽略错误进行重试。
(二)实现方式
错误码可以和国际化结合起来实现
在springboot项目的resources目录中创建i18n文件夹,在文件夹下创建messages.properties等三个国际化配置文件,IDEA会自动创建Resource Bundle并绑定这三个国际化配置文件。
messages.properties和messages_zh_CN.properties文件配置参考如下:
00000=请求成功
A0001=用户端出错
A0002=参数 {0} 缺失
A0003=参数 {0} 长度不合法
A0004=参数 {0} 格式不正确
A0005=参数 {0} 类型不合法
A0006=参数 {0} 状态已过期
A0007=参数 {0} 非法
A0008= {0} 不存在
A0009= {0} 已存在
A0010= {0} 重复
A0011= {0} 不允许被删除
A0101=用户权限不足
A0102=用户操作频繁
B0001=当前系统出错
B0101=系统正忙,请稍后再试
C0001=第三方服务出错
messages_en_US.properties文件配置参考如下:
00000 = request successful
A0001 = client error
A0101 = missing parameter {0}
A0201 = illegal type of parameter {0}
A0301 = parameter {0} exceeds limit
A0401 = invalid parameter {0}
A0501 = {0} has expired
A0601 = result {0} does not exist
A0701= result {0} already exists
A0801 = delete {0} forbidden
A1001 = insufficient user rights
B0001 = current system error
B0101 = the system is busy, please try again later
C0001 = third party service error
其中,A代表用户错误,B代表当前系统错误,C代表依赖的第三方服务错误,用0001表示第一类宏观错误。
错误码可以自己设计,不断自增,先到先得,以100为步长作为大类分类。
一般默认中文,然后设计好后,直接拿去翻译,再粘贴回来。
为了通用匹配错误,我用了{0}来匹配。如果想设置个性化信息,可以接着往后配置A0102…等等提示信息。
(三)错误码举例
1.参数缺失
setEmail(null);
若传进的email为空,则判为参数缺失。
2.参数长度不合法
setEmail("99999999999999999999999999999@qq.com");
若传进的email的字符串长度超出或少于预设值,则判为参数长度不合法。
3.参数格式不正确
setEmail("123456");
若传进的email的格式不符合“xxx@xxx.xx”的格式,则判为格式不正确。
4.参数类型不合法
setEmail("123456@error.com");
若传进的email的后缀不是服务端允许的“@qq.com、@163.com”等格式,则判为参数类型不合法。
以上为从输入就能做出的验证,接下来是必须查数据源或经计算才能做出的验证
5.参数状态已过期
checkToken("daf2$11.sdf34asasf4ewrjjmp94xg");
若输入的token值的有效期与当前时间比较已超过,则判为参数状态已过期。
6.参数非法
checkToken("daf2$11.sdf34asasf4ewrjjmp94xg");
若输入的token值解密失败,则判为参数非法。
7.数据不存在
getUser("123");
updateUser("123");
deleteUser("123")
若查询的userid在数据库中查不到,则判为数据不存在。
8.数据已存在
addUser("123");
若添加的用户userid在数据库中已存在,为保证唯一性,则判为数据已存在。
9.数据重复
setEmail("123456@qq.com");
setEmail("123456@qq.com");
若传进的email为无变化,则判为参数重复输入。
错误码,也不用太多(几百上千种),要不然自己眼花缭乱,陷入麻烦里了。最好做到,不查文档,就了解是什么错误了。
三、工具类
需要自行将错误码进行封装,默认是中文
/*** 错误码相关方法*/
public class ErrorCodeUtils {/*** 获得错误码对应的提示信息* @param errcode 错误码* @param params 匹配参数* @return 返回错误提示信息*/public static String getMessage(String errcode, String ...params){ResourceBundle bundle = ResourceBundle.getBundle("i18n/messages", Locale.getDefault());String msg = bundle.getString(errcode);MessageFormat messageFormat = new MessageFormat(msg);return messageFormat.format(params);}
}
然后调用编写的方法
@Test
public void testI18n() throws IOException {System.out.println(ErrorCodeUtils.getMessage("A0101","ID"));
}
//输出:参数ID缺少
Springboot项目错误码的设计与实现相关推荐
- 错误码如何设计才合理?
简介:对于错误码的设计,不同的开发团队有不同的风格习惯.本文分享阿里文娱技术专家长统对于错误码的看法,希望从错误码使用的不同场景讨论得到一个合理的错误码规约,得到一个面向日志错误码标准和一个面向外部传 ...
- 错误码如何设计才合理?(转载)
一 前言 在工作中,接触过不少外部接口,其中包括:支付宝,微信支付,微博开发平台,阿里云等等.每家公司错误码风格都不尽相同,有使用纯数字的,有使用纯英文的,也有使用字母和数字组合的.也接触过很多内部系 ...
- SpringBoot自定义错误码,并支持国际化
实现效果:不同的业务模块用不同的错误编码 一.错误码封装 获取错误信息接口类,所有的错误都要统一实现该接口类 public interface BaseErrorCode {/*** 获取错误码* @ ...
- 小编教您Springboot项目中异常拦截设计与处理
项目运行过程中会出现各种各样的问题,常见的有以下几种情况: 业务流程分析疏漏,对业务流程的反向操作.边界分析设计不充分 调用外部服务.调用外部系统出现的超时.错误.返回值与预期不符 外部资源连通性问题 ...
- 什么是好的错误消息? 讨论一下Java系统中的错误码设计
简介:一个好的Error Message主要包含三个部分:Context: 什么导致了错误?发生错误的时候代码想做什么?The error itself: 到底是什么导致了失败?具体的原因和当时的数据 ...
- 如何设计系统的错误码及错误信息
作者:朱金灿 来源:http://blog.csdn.net/clever101 一个软件系统,肯定是涉及到很多错误信息.比如用户执行出错了,软件需要将错误信息返回给用户.那么如何设计错误码及错误信息 ...
- Linux系统C/C++通用错误码实现模板
背景 公司C++项目初期是安排不同的人编写不同的模块,有嵌入式ARM的,有socket协议的,有mysql的,有redis的,不同人风格不同.由于当时我还在运维小组搞docker,没参与规则的制定,后 ...
- Springboot项目架构设计
导航 前言 流水线 架构的艺术 项目架构 理解阿里应用分层架构 superblog项目架构 结语 参考 本节是<Spring Boot 实战纪实>的第7篇,感谢您的阅读,预计阅读时长3mi ...
- SpringBoot 项目tomcat插件启动报错 java.lang.NoClassDefFoundError: javax/el/ELManager
问题描述: SpringBoot项目 tomcat插件启动出现下面的问题: ERROR 2021-04-07 08:42:03,129 org.springframework.boot.SpringA ...
最新文章
- AI当红娘,真的能帮你摆脱单身吗?
- 删除空文件夹 linux,Linux中find批量删除空文件及空文件夹脚本
- tomcat-users.xml 配置(转的)
- 1054 The Dominant Color (20 分)【难度: 简单 / 知识点: 思维】
- MIP 2016年终总结
- ppt讲解中的过渡_PPT黑科技,只用一张图做出3D动画
- 漫画:8年估值千亿美金的字节跳动是如何修炼的
- 云栖科技评论第57期:技术拓展科学边界 科学激发技术创新
- python中的[1:]、[::-1]、X[:,m:n]和X[1,:]
- PLsql 永久注册码
- 黑马程序员Python教程的代码--植物大战僵尸游戏代码
- pyqt4安装问题小结(一)
- [04-07]最新精选绿色软件每日更新(小熊整理)
- 魔兽世界燃烧的远征最新服务器,魔兽世界怀旧服人口普查最新2021 5月服务器阵营比例介绍...
- 魔法门之英雄无敌3 android,魔法门之英雄无敌3 v0.86.04
- 【shell】shell是什么,shell脚本又是什么?
- 打开Windows自带的画图工具
- 正则表达式判断是不是手机号
- 计算机计算资产分析表,财务指标计算公式excel,用EXCEL做财务指标分析,如何使用其他工作簿做公式计算??...
- python批量删除图片和空文件夹