文档规范
文档规范
接口文档规范
(必须)做到业务逻辑自洽(必须)提供标准的请求示例与响应示例(必须)请求示例配备字段说明,并做好字段规则说明(重要)接口字段命名与数据库保持一致(重要)响应示例:复杂业务接口提供详细的字段注释 (推荐)响应示例:简单业务接口提供简单注释
接口命名规范
统一用POST请求(不用Restful),文件接口用formdata,其他用json,方便集成时可能遇到到统一过滤拦截转换等
API版本控制
API的版本号统一放入URL,如:https://api.example.com/v{n}/,n代表版本号,分为整形和浮点型
提测或用户部署为节点
大迭代用整形版本号:大功能版本发布形式;具有当前版本状态下的所有API接口,例如:v1,v2 小迭代用浮点型:为小版本号,只具备补充api的功能,其他api都默认调用大版本号的API,例如v1.1,v1.2
接口命名前缀
| 前缀 | 作用 | 示例 |
|---|---|---|
open | 互联网公开接口,无需认证 | /open/v1.2/user/接口方法名 |
auth | 互联网认证接口,需要认证 | /auth/v1.2/user/接口方法名 |
lan | 局域网内部接口,仅局域网内调用 | /lan/v1.2/user/接口方法名 |
self | 局域网私有接口,仅局域网内私有领域服务调用 | /self/v1.2/user/接口方法名 |
paas | 平台业务接口,为外部业务提供集成对接支持 | /paas/v1.2/user/接口方法名 |
paasCallback | 平台回调接口,由外部服务实现,平台回调 | /paasCallback/v1.2/user/接口方法名 |
接口方法名规范
- 新增:
POST /v1.2/user/save - 删除:
POST /v1.2/user/delete - 更新某字段:
POST /v1.2/user/updatePassword - 更新对象:
POST /v1.2/user/update - 列表:
POST /v1.2/user/list - 详情:
POST /v1.2/user/getById - 分页:
POST /v1.2/user/page - 其他:
POST /open/v1.2/user/动作
| HTTP方法 | 接口动作类型 | 接口方法名前缀 | 接口动作解释 | 示例 |
|---|---|---|---|---|
| POST | 增 | insert | 新增、插入、添加 | POST /open/v1.2/user/insert |
| DELETE | 删 | delete | 物理删除、逻辑删除 | DELETE /open/v1.2/user/delete |
| PUT | 改 | update | 修改、更新 | PUT /open/v1.2/user/updatePassword |
| GET | 查 | get | 单条(一个结果) | GET /open/v1.2/user/getById |
| GET | 查 | list | 列表(多个结果) | GET /open/v1.2/user/list |
| GET | 查 | page | 分页 | GET /open/v1.2/user/pageLikeUsername |
| POST | 动作 | act | 登录、注册、上传、下载 重置、提交、搜索、支付 | POST /open/v1.2/user/actLogin POST /open/v1.2/user/actRegister POST /open/v1.2/user/actPasswordRest POST /open/v1.2/user/actSearch |
请求定义
常见请求header约定
| 参数名称 | 参数类型 | 最大长度 | 描述 | 示例 |
|---|---|---|---|---|
tenantSys | String | 36 | 系统租户:一级租户(dict_tenant_sys) | sc |
tenantCo | String | 36 | 企业租户:二级租户 | 27b106951b964851b73e5d2864e9257b |
Accept-Language | String | 20 | i18n国际化-语言切换 | zh-CN |
clientId | String | 20 | 客户端请求来源APP WAP PC | APP |
timestamp | String | 17 | 发送请求的时间,格式:yyyyMMddHHmmssSSS | 20180505121212222 |
常见请求参数约定
| 参数名称 | 参数类型 | 最大长度 | 描述 | 示例 |
|---|---|---|---|---|
pageNum | Int | 5 | 分页查询-当前页 | 1 |
pageSize | Int | 6 | 分页查询-每页显示条数 | 20 |
orderBy | String | 50 | 分页查询-排序字段 | id,name,age |
sign | String | 344 | 请求参数签名串 | djdu7dusufiusgfu |
signType | String | 10 | 生成签名字符串所使用的算法类型 | RSA |
accessToken | String | 36 | 访问令牌,UUID5 | 65dbec7a-1df5-5413-bf41-9d4e41ee4ba7 |
常见参数约定
| 参数名称 | 参数类型 | 最大长度 | 描述 | 示例 |
|---|---|---|---|---|
count | Long | 20 | 分页统计条数 | 100 |
响应定义
响应体约定
| 参数名称 | 参数类型 | 最大长度 | 描述 | 示例 |
|---|---|---|---|---|
code | Int | 3 | 响应状态码(同步HTTP状态码) | 200 |
msg | String | 30 | 响应提示(除状态码600外,此msg皆表示给开发者的提示) | 成功 |
flag | Boolean | 响应状态 | true | |
traceId | String | 链路追踪码 | 1cc00a1d8be14acc98457b23b8f5ab9f | |
data | Object | 业务数据 | 【钉钉】通知结果: |
msg提示约定:
- 除状态码600外,此msg皆表示服务端给客户端(即开发者)的请求提示
- 一般情况其它错误提示,如:500,服务器内部错误等,需前端结合各自业务情况统一拦截处理,转换为优化的用户提示,如:
网络开小差了,请稍后重试... - 优好的用户提示,甚至可到页面步骤级别,不同步骤错误基于不同的友好提示。
响应示例:
{
"code": 200,
"msg": "成功",
"flag": true,
"traceId": "1cc00a1d8be14acc98457b23b8f5ab9f",
"data": "【钉钉】通知结果:{\"errcode\":0,\"success\":true,\"errmsg\":\"ok\"}"
}
code定义:
public enum ResultEnum {
// 200 - 正确结果
SUCCESS(200, "成功"),
LOGGED_IN(210, "会话未注销,无需登录"),
// 300 - 资源、重定向、定位等提示
RESOURCE_ALREADY_INVALID(300, "资源已失效"),
MOVED_PERMANENTLY(301, "Moved Permanently"),
FILE_EMPTY(310, "文件上传请求错误,获得文件信息为空,求先使用测试工具(如:postman)校验,同时文件必须有明确的匹配类型(如文本类型:.txt)"),
// 400 - 客户端错误
BAD_REQUEST(400, "错误的请求,参数校验未通过,请参照API核对后重试"),
UNAUTHORIZED(401, "未登录或登录已失效(Unauthorized)"),
ATTACK(402, "非法访问"),
FORBIDDEN(403, "无权限(Forbidden)"),
NOT_FOUND(404, "Not Found"),
METHOD_NOT_ALLOWED(405, "方法不允许(Method Not Allowed),客户端使用服务端不支持的 Http Request Method 进行接口调用。"),
GONE(410, "当前API接口版本已弃用,请客户端更新接口调用方式"),
UNSUPPORTED_MEDIA_TYPE(415, "Unsupported Media Type"),
TOO_MANY_REQUESTS(429, "频繁请求限流,请稍后重试(Too Many Requests)"),
PARAM_VOID(432, "参数为空"),
PARAM_CHECK_NOT_PASS(433, "参数校验未通过,请参照API核对后重试"),
PARAM_VALUE_INVALID(434, "参数校验未通过,无效的value"),
PARAM_DECRYPT_ERROR(435, "参数解密错误"),
// 500 - 服务器错误
INTERNAL_SERVER_ERROR(500, "服务器内部错误(Internal Server Error)"),
REQUEST_ERROR(501, "请求错误"),
BAD_GATEWAY(502, "Bad Gateway"),
SERVICE_UNAVAILABLE(503, "Service Unavailable"),
GATEWAY_TIMEOUT(504, "Gateway Timeout"),
DATA_STRUCTURE(505, "数据结构异常"),
DB_ERROR(506, "数据结构异常,请检查相应数据结构一致性"),
CLIENT_FALLBACK(507, "网络开小差了,请稍后重试..."),
CLIENT_FALLBACK_ERROR(508, "当前阶段服务压力过大,请稍后重试..."),
TYPE_CONVERT_ERROR(509, "类型转换错误"),
// 600 - 自定义错误提示
ERROR_PROMPT(600, "错误提示,请使用具体的错误提示信息覆盖此msg");
}
自定义组合API
把当前用户需要在第一时间内容加载的多个接口合并成一个请求发送到服务端,服务端根据请求内容,一次性把所有数据合并返回,相比于页面级API,具备更高的灵活性,同时又能很容易实现页面级API功能。
地址:api/v1/testApi
传入参数:
{
"data": [
{
"url": "api1",
"type": "get",
"data": {}
},
{
"url": "api2",
"type": "get",
"data": {}
},
{
"url": "api3",
"type": "get",
"data": {}
}
]
}点击复制错误复制成功
返回数据:
{
"code": 200,
"flag": true,
"msg": "成功",
"data": [
{"code": 200,"msg": "","data": []},
{"code": 200,"msg": "","data": []},
{"code": 200,"msg": "","data": []}
]
}
工程结构规约
包名规范(业务命名法)
- 业务命名法,以一个业务为一个包(如:红包活动,redbag)
- 一个包中可以包含多个相同业务类
以下定义固定的包命名规范:
ai.yue.library.test 根路径:SpringBoot中一般放Application启动类
ai.yue.library.test.aspect 切面:业务统一拦截处理
ai.yue.library.test.config 配置:服务配置定义
ai.yue.library.test.constant 常量:业务常量定义
ai.yue.library.test.controller MVC控制层:接口映射与参数处理
ai.yue.library.test.service MVC服务层:业务逻辑处理
ai.yue.library.test.mapper MVC数据持久层:数据库操作
ai.yue.library.test.forest.open HTTP客户端:用于调用互联网公开接口
ai.yue.library.test.forest.auth HTTP客户端:用于调用互联网认证接口
ai.yue.library.test.forest.lan HTTP客户端:用于调用局域网内部接口(微服务之间通信)
ai.yue.library.test.forest.self HTTP客户端:用于调用局域网私有接口,仅局域网内私有领域服务调用
ai.yue.library.test.forest.paas HTTP客户端:用于调用平台方(如:公有云)提供的接口
ai.yue.library.test.forest.paasCallback HTTP客户端:用于回调业务方提供的接口(自身为平台方)
ai.yue.library.test.entity 数据库实体对象:数据库一对一实体映射封装
ai.yue.library.test.dto DTO数据传输对象:多表联查实体封装与业务对象封装等
ai.yue.library.test.ipo IPO接口入参对象:接口请求参数封装与校验
ai.yue.library.test.vo VO业务视图对象:接口返回参数封装点击复制错误复制成功
Service/Mapper层方法命名规约
- 获取单个对象的方法用
get做前缀。 - 获取多个对象的方法用
list做前缀。 - 分页多个对象的方法用
page做前缀。 - 获取统计值的方法用
count做前缀。 - 插入的方法用
save做前缀。 - 删除的方法用
delete做前缀。 - 修改的方法用
update做前缀。
POJO领域模型命名规约
- Entity:数据对象,一般情况下与数据库表结构一一对应,通过 Mapper 层向上传输数据源对象。
- DTO(Data Transfer Object):数据传输对象,Service 向外传输的对象。使用场景:第三方接口固定返回对象,多表链接对象、特殊业务固定传输对象。
- IPO(Interface Param Object):接口入参对象,可实现对参数的多层次嵌套封装与逻辑校验。
- VO(View Object):业务视图对象又称显示层对象,通常是 Web 向模板渲染引擎层传输的对象。
POJO 是 DO/DTO/BO/VO 的统称,禁止命名成 xxxPOJO。
数据库设计规约
请遵守《阿里巴巴Java开发手册》数据库设计规约,并确保整体设计风格的一致性。 表的设计需符合业务逻辑需求,同时应最大程度上的降低 开发、维护、扩展 成本,并允许拥有一部分合理范围之内的设计模式与理念。 服务中台的数据结构应遵循共享原则,不应出现与业务绑定的特殊字段,需做特殊兼容时可考虑扩展设计,如:json、jsonschema、特殊占位字段、业务方自行扩展等方式。
命名规约
增加一个名词约定库,用于统一常用名词在变量命名时的规范使用,避免一个单词被用于多种意思,同一字段使用了不同单词
同一含义的数据库字段命名与接口参数命名尽量保持一致(包括数据库字段注释与接口参数注释)
关联字段命名时,应保留关联标识与语义
枚举类型命名保留枚举语义后缀,没有语义后缀的使用enum结尾,同时枚举注释应该将枚举值全部列举,如:
type、status等,代码中必须定义枚举类与之对应复数变量使用
s结尾,如果变量值是一个待分割的数组,请添加注释说明(如:,分割)表示是否的字段,统一0代码否,1代表是
枚举规约
数据字典表、字符串类型(伪枚举)、数字类型使用场景规约
| 类型 | 适用范围 | 规约 |
|---|---|---|
| 数据字典表 | 行业标准数据,如:行政区划 需动态维护的常量数据,如:类型、分类 | 固定字典 dict_final_xx,不变的或行业标准的数据 常规字典 dict_xx,业务自定义的数据 |
| 字符串类型(伪枚举) | 拥有流转状态的业务,如:订单状态 没有流转状态的业务,如:用户状态(正常1、注销2、禁用3) | 数据库中禁用enum类型,当字符串(伪枚举)类型需要参与业务逻辑时, 程序中必须定义枚举来解析字符串 ,哪怕只是一个判断或校验 |
| 数字类型 | 禁止使用 1,2,3,4,5... 之类的数字代替枚举类型 ,数字类型语义化表示不明确, 并且在有流转状态的业务中,会出现乱序现象,如:最初定义的1234567由于业务状态变更成了1236745 | 禁止使用数字代替枚举 |
- 在数据库中,请使用字符串代替
enum类型的使用 - 枚举值即常量值,命名时请遵循大写字母的下划线命名法(
AAA_BBB_CCCC),拥有相同规则的常量用前缀表示,不应放在中间或后面 - 在所有文档(接口、程序、数据库)中都应该提供完整清晰的注释(如:
MAN=男、WOMAN=女) - 当枚举值需参与业务逻辑时,程序中必须定义枚举类来解析字符串值
交付评审规约
- 文档说明,优雅的概括本次变动与自己的设计思路
- 表的位置(链接地址 - 数据库)
- 变更字段的位置
- 完善的表注释与字段注释
- 规范的字段命名,关联字段保持统一风格(不规范的字段命名改动,需提出并获得评审通过)
- 删除表需特别说明 并 加以强调
新增表
- 详细概括表的作用与设计思路
- 提供全表DDL
- 表中的约束与索引
- 表与表之间的关系(禁止使用外键)
更改表
- 字段变更的说明
- 提供全表DDL
- 本次改动DDL
- 表中的约束与索引
维护规约
数据库设计并非一蹴而就,开发中发现不合理与遗漏的表设计,需对其进行修改时,必须对其所有变更进行DDL记录与变更说明。 项目上线或发布时,数据库同步便可参照本次变更记录做对比,考虑是否有数据结构安全隐患,以作数据的处理。规则如下:
- 每次变动记录详细的变动DLL语句并解释此次变更是为什么
- 变更前先明确表设计初衷,后续为何变更,初衷是否改变,是否需要更新表初衷
中间件安全
中间件本文泛指如:Nacos、MySQL、Redis、RocketMQ、Elasticserch、Kibana、Rancher、zipkin、plumelog等
中间件使用默认密码、弱密码、无密码都是最低级的安全问题,养成良好习惯改个密码不费事(包括你的开发环境、测试环境)。
SpringBoot安全
应用监控Actuator安全隐患(严重)
当你使用百度搜索Actuator相关博客时,你会看到清一色的如下配置:
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: always点击复制错误复制成功
这些博客中并未说明这样的配置会带来重大安全隐患,而大家都是从小白到入门的过程,几乎不会深究上述配置的问题,所以如果你真的在你的应用中添加了上面的配置,并且未加入spring-boot-starter-security做安全认证, 那么你的数据库连接信息包括你的用户名与密码等已在内网中裸奔,这个时候如果你的服务暴露给了公网,那么恭喜你这些信息已在全网敞开。
重大安全隐患路径(不同版本的SpringBoot端点路径不一样,下面是SpringBoot2.x的路径):
actuator/env获取服务运行时的全部环境配置(包括你的数据库连接信息)actuator/heapdump下载服务运行时的堆栈信息,可以根据actuator/env路径暴露的key,查找到服务内存中的配置信息,如:密码
👉扩展阅读:SpringBoot组件安全之Actuator👉扩展阅读:SpringBoot渗透之Actuator获取数据库密码👉扩展阅读:Springboot之actuator配置不当的漏洞利用
yue-library-auth-*模块针对Actuator组件的安全问题进行了严谨的处理,其中就包括对actuator/端点配置了独立的访问密码(默认为随机密码), 未进行Actuator安全处理的项目,可依赖或参考yue-library-auth-*任意模块实现Actuator安全。
jar包信息泄漏安全隐患
在进行springboot打包时,应将保密文件排除,避免将这些文件打入到jar中。
【推荐】保密配置文件命名,使用
confidential作为命名后缀,有助于在打包时进行统一排除。
正例:
application-confidential.yml、
application-prod-confidential.yml<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <excludes> <exclude>*confidential*.properties</exclude>--> <exclude>*confidential*.yml</exclude> </excludes> </configuration> </plugin> </plugins> </build>点击复制错误复制成功
启动项目
流程:下载项目 ➡ 导入IDE ➡ 初始化数据库 ➡ 运行项目 ➡ 调用接口测试
resources/docs文件夹下存放着如下内容:
- DDL脚本:用于MySQL数据库表初始化
- API接口文档:用于类似Postman的接口测试(提供请求示例)与详细的接口文档(浏览器直接打开即可)
