REST API规范

目录

  • 一、REST相关规范
    • 1.1 Http Method
    • 1.2 REST接口格式
    • 1.3 Http Status
    • 1.4 版本控制
  • 二、SpringMVC相关规范
    • 2.1 参数校验
    • 2.2 响应结果
    • 2.3 接口全局异常处理
    • 2.4 参数校验提示信息支持国际化
    • 2.5 响应码规范

REST+ JSON已成为Http接口的事实标准,本文给出我平时推荐的REST API规范及相关注意事项。

一、REST相关规范

1.1 Http Method

之前见过技术团队为了前后端交互方便,所有的请求都使用POST方法,支持queryParam和Json Body两种参数形式。如此虽然简化了组件的开发难度,但却丢失了REST的语义。我推荐你使用一切可用的 HTTP 方法,因为这就是它们的目的。你可以把所有的 CRUD 操作映射到 POST、GET、UPDATE 和 DELETE。我只想让你别用 GET 来创建或更新数据。请不要这样做!

关于Http Method的推荐使用方式如下:
GET
读取(查询)数据,该方法不会改变后端数据,它只读取数据。GET 请求是安全的,可多次重复执行的,并且不会对系统存储的数据产生影响。
POST
保存(新增)数据,意味着你将在数据库创建一条新记录,新增的内容(参数)支持多种格式(Content-Type):multipart/form-data、 x-www-form-urlencoded 、raw(application/json,text/plain等),推荐使用 application/json 的形式,使用JSON数据可以支持更多复杂的请求(例如支持批量列表、对象嵌套等)。POST 操作是不安全的,因为它会在服务器端改变一些东西,并且向同一个POST端点(例如新增数据接口)发出同样的2个请求会导致创建2个不同的资源。
PUT
更新数据,根据数据ID进行全量的更新(对资源对象的所有属性进行更新),PUT 也是不安全的操作,因为它在服务器端做了改动,但PUT操作应该是幂等(idempotent)的,即多次重复修改后资源数据都是一样的结果。
DELETE
删除数据,这个操作肯定不安全的,会导致后端数据的删除,不过删除接口也可以做成幂等的,支持重复删除,若删除不存在的记录也意味着删除成功。
PATCH
更改数据的一部分,相较于PUT对资源对象的所有属性都进行更新,PATCH仅对资源对象的部分属性进行更新。PATCH既不是安全的,也不是幂等的(例如更新订单状态,状态的更改是有先后顺序的,在已支付状态修改为发货状态,多次重复修改为发货状态时会提示已不是已支付状态)。

既然我们已经了解了基础知识,那么接下来就是实际生活中所发生的事情。大部分人都是用 GET、POST,还有一些人使用 PUT 和 DELETE。我几乎没有见过有谁在用 PATCH。我推荐你使用一切可用的 HTTP 方法,因为这就是它们的目的。你可以把所有的 CRUD 操作映射到 POST、GET、UPDATE 和 DELETE。我只想让你别用 GET 来创建或更新数据。请不要这样做!

关于Http Method的使用场景总结如下表:

HTTP动词操作含义幂等性安全性
GET从服务器取出资源
(一项或多项)
POST在服务器新建一个资源
PUT在服务器更新资源
(客户端提需供改变后的完整资源)
PATCH在服务器更新资源
(客户端仅提供改变的属性)
不确定
DELETE从服务器删除资源

1.2 REST接口格式

REST接口URL定义推荐参照以下规则:

URL规则示例
不要用动词,而是用名词/users
/goods
用复数替代单数使用/users,而不推荐/user
尽量使用单个单词而不是多个单词,
若必须使用多单词推荐snake_case
/users/{userId}/roles
/users/{userId}/roles_permissions

下面给出REST接口各场景下method、url、参数及响应结果的参考规范:

注: 以下接口定义采用 用户管理users、角色管理roles 为例。

场景HTTP动词URL格式参数形式结果形式幂等性
查询一个资源GET/users/{userId}Path参数JSON响应体
根据不同条件查询资源列表GET/users?name=luo&sex=1Query参数JSON响应体
查询资源关联的资源GET/users/{userId}/rolesPath参数JSON响应体
下载资源导入excel模版GET/users/excel/templateapplication/octet-stream
通过excel导出资源GET/users/excelQuery参数application/octet-stream
新增资源POST/usersJSON请求体JSON响应体
新增资源关联的资源POST/users/{userId}/rolesPath参数
JSON请求体
JSON响应体
通过excel导入资源POST/users/excelmultipart/form-dataJSON响应体
修改资源PUT/usersJSON请求体JSON响应体
修改资源关联的资源PUT/users/{userId}/rolesPath参数
JSON请求体
JSON响应体
修改资源的一部分PATCH/usersJSON请求体JSON响应体不确定
删除一个资源DELETE/users/{userId}Path参数JSON响应体
删除多个资源DELETE/users/{userIds}Path参数
(多个ID使用英文逗号分隔,例如/users/1,2,3)
JSON响应体
删除资源关联的资源DELETE/users/{userId}/roles/{roleId}Path参数JSON响应体

注:
若GET请求查询参数过长(极端情况),
可考虑使用POST + JSON Body,
可以理解为每次查询的结果是一个新创建的临时结果集。

1.3 Http Status

  • 信息型响应代码(以 1xx 开头)
  • 成功响应代码(以 2xx 开头)
  • 重定向响应代码(从 3xx 开始)
  • 客户端错误响应代码(从 4xx 开始)
  • 服务器错误响应代码(以 5xx 开头)

1.4 版本控制

推荐在REST接口的URL添加版本号前缀,格式如下:

# V1版本
/api/v1/...
/api/v1/users/...
/api/v1/roles/...# V2版本
/api/v2/...
/api/v2/users
/api/v2/rolse

切记在升级应用版本时,同步升级接口URL中对应的版本号,
例如应用使用语义化版本号:MAJOR.MINOR.PATCH格式时,
URL中的版本号即对应MAJOR版本,所以在升级MAJOR版本号时需同步升级接口版本号。
在URL中添加版本号,不仅可以方便不同版本的接口管理,也可以帮助开发人员在纷杂的线上环境中通过浏览器控制台、接口定义等一眼识别出目标系统的版本,快速定位问题。

二、SpringMVC相关规范

2.1 参数校验

1)集成Java Validation完成基础校验
通过集成Java Validation相关注解@Validated、@Valid、@NotBlank等,完成输入参数的基础校验。

更多内容请访问: JSR 380: Bean Validation

通过使用Java Validation尽可能让错误前置,避免必填项、数字、日期格式等低级错误穿透到业务逻辑或持久层。

若存在复杂的业务校验,如编码是否唯一,数据关联验证等,则在Service层通过手动编码完成

注:
关于SpringBoot Validation的更多介绍可参见:
https://luoex.blog.csdn.net/article/details/120074866

2)集成校验的层次
若存在Service层,则推荐将校验逻辑统一放置到Service层。

为什么不在Controller层校验,而是在Service层校验?

  1. 输入内容的校验也是业务规则的一部分
    Service层为核心业务的实现层,而基础的输入内容的校验(非空、长度等)也是业务规则的一部分,理应由Service层负责。
  2. 替换Controller层会导致校验规则的缺失
    Controller层相较于Service层更偏向于技术接口层,仅负责Http通信协议的处理,并将业务处理委托给Service层。考虑到架构的可持续演进,Controller层作为接口层也可能会被替换为其他的通信协议,如gRPC等,若将输入内容校验放到Controller层,则替换其他通信协议时会导致校验规则的缺失。
  3. Service层间的彼此调用也需要保证输入内容的合法性
    若将校验放到Controller层,则Service层的不同Service实现间相互调用将无法触发校验,可能会导致业务异常,而将校验逻辑放到Service层则可以保证不同Service实现间相互调用将正常触发校验,显然将校验逻辑放到Service层更合理。

3)关于校验提示信息
若使用Java Validation内建注解来完成基础参数的校验,校验注解中的message无需设置(保持为空即可),由校验框架自行生成(支持国际化)。原则上该部分校验信息不是给用户看的,是给开发人员联调时排查问题的,所以保持默认提示信息即可。强烈推荐在前端(如浏览器端、移动端)页面完成基础的参数校验,避免不合规的数据传到后端,而后端接口中的参数校验只作为最后的闸门,避免异常业务数据进入系统中。

对于Service中的自定义校验逻辑,若校验不通过,需给出相应的响应码及提示信息(可通过自定义业务异常实现,如BizException)。

2.2 响应结果

1)SystemResponse
推荐封装统一的SystemResponse :

class SystemResponse<T> {/*** 返回状态码*/public String code;/*** 返回消息信息*/private String msg;/*** 返回业务数据*/private T data;//getter/setter...    
}

其中code表示响应码,由业务实现方自行定义,
msg表示响应提示信息,在发生业务异常时用来给出相应的错误提示,
data则表示具体的响应数据,例如调用查询商品接口时返回的商品详情信息、商品分页列表等。

2.3 接口全局异常处理

API接口层(Controller层)需捕获并处理一切业务异常,并通过日志框架记录相关异常,然后通过SystemResponse统一封装响应信息,接口层的异常信息不可直接暴露到响应结果中,接口统一返回Http Status 200,例如在SpringMVC中可采用@ControllerAdvice实现。

2.4 参数校验提示信息支持国际化

关于Java Validation相关注解中的message信息,如无特殊需求默认保持空即可
若需设置自定义提示信息,可支持直接设置错误提示信息【不推荐】:

@NotBlank(message ="姓名不能为空")
private String name;

又或者【推荐】通过{…}指定国际化信息的key,支持国际化提示信息(需结合Spring Message国际化):

@NotBlank(message ="{BIZ.USER.NAME.NOT_BLANK}")
private String name;

关于国际化KEY的命名规范,推荐格式如下:

格式: {APP}.{MODULE}.{PROP}.{RULE}

示例:
BIZ.GOODS.NAME.NOT_NULL=商品名称不能为空
RBAC.USER.USER_ACCOUNT.LENGTH=用户账号长度不能超过256

2.5 响应码规范

对于Service中的自定义校验逻辑,若校验不通过,可通过抛出BizException结束相关业务处理,在抛出异常时需同步给出相应的响应码,该异常会被全局异常处理器捕捉并处理,后续该响应码会作为SystemResponse的code返回给前端:

//抛出业务异常
throw new BizException(yourRespCode, yourRespMsg)

亦可通过工具类AssertUtils生成BizException并给出相应的响应码:

//判断条件是否成立,若不成立则抛出业务异常
AssertUtils.assertTrue(yourAssertCondition, yourRespCode)
//判断条件是否不成立,若成立则抛出业务异常
AssertUtils.assertFalse(yourAssertCondition, yourRespCode)
//判断对象是否为空,若非空则抛出业务异常
AssertUtils.assertNull(yourObj, yourRespCode)
//判断对象是否不为空,若为空则抛出业务异常
AssertUtils.assertNotNull(yourObj, yourRespCode)
//其他:assertBlank, assertNotBlank, assertEmpty, assertNotEmpty

其中响应码的命名规范,推荐格式如下:

格式: {APP}.{MODULE}.{NUM_CODE}

其中NUM_CODE建议使用如下前缀:
输入异常: 100…
内部业务处理异常: 200…
调用第三方服务异常: 300…

具体示例:
RBAC.COMMON.100101
RBAC.COMMON.100201
RBAC.USER.200101
RBAC.USER.200201

可为响应码定义相应的国际化提示信息,在全局异常处理逻辑中会提取BizException中的响应码所对应的国际化提示信息,并将该提示信息设置到SystemReponse中的msg属性,用于给出更详细的业务提示信息。结合前面给出的响应码格式定义,给出如下参考国际化信息定义:

# 输入异常
RBAC.DEPT.100101=组织编码已存在
RBAC.DEPT.100102=组织编码不存在
RBAC.DEPT.100201=组织父编码不存在# 内部业务处理异常
RBAC.DEPT.200101=组织下存在已绑定的用户,请先解除绑定后再删除
RBAC.DEPT.200201=组织下存在子组织,请先删除子组织后再删除# 调用第三方服务异常
RBAC.DEPT.300101=同步组织信息异常

参考:
REST 十诫
RESTful GET,如果存在大量参数,是否有必要变通一下?
@RequestParam和@PathVariable传递数组,json数组类型参数的实验

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/829946.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大白菜启动U盘想格式化但格式化不了

部分区域被修改分区表保护起来了。直接格式化的话&#xff0c;里面的文件夹都还在。根本格式化不了。特别是可用容量并未还原出来。 进入计算机管理》磁盘管理&#xff0c;看到U盘盘符。别搞错了。删除掉里面的已经分的区域和未分区区域&#xff0c;让它还原成一个整体。退出。…

Webpack-入门

定义 静态模块&#xff1a;指的是编写代码过程中的html&#xff0c;css&#xff0c;js&#xff0c;图片等固定内容的文件 打包&#xff1a;把静态模块内容压缩、整合、翻译等&#xff08;前端工程化&#xff09; 1&#xff09;把less/sass转成css代码 2&#xff09;把ES6降级…

webpack 入口和出口的最佳实践

入口和出口的最佳实践 {ignore} 具体情况具体分析 下面是一些经典场景 一个页面一个JS 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 源码结构 |—— src|—— pageA 页面A的代码目录|—— index.js 页面A的启动模块|—— ...|—— pageB 页面…

matlab学习007-已知离散时间系统的系统函数并使用matlab绘制该系统的零极点图;判断系统的稳定性;幅频和相频特性曲线

目录 题目 离散时间系统的系统函数&#xff1a;H(z)(3*z^3-5*z^210z)/(z^3-3*z^27*z-5) 1&#xff0c;绘制该系统的零极点图 1&#xff09;零极点图 2&#xff09;代码 2&#xff0c;判断系统的稳定性 1&#xff09;判断结果 2&#xff09;代码 3&#xff0c;试用MATL…

闲话 ASP.NET Core 数据校验(一):内置数据校验

前言 所谓输入的是垃圾&#xff0c;输出也必然是垃圾&#xff0c;有多少安全问题隐藏在请求的数据中&#xff0c;所以永远不能相信来自用户端的输入。 对请求数据的合法性进行校验&#xff0c;不仅有助于提升用户界面的友好性&#xff0c;而且有助于提高后台程序的安全性和稳…

【车载开发系列】UDS诊断时间参数说明

【车载开发系列】UDS诊断时间参数说明 一. 应用层诊断时间参数 1&#xff09;P2 CAN_Client 诊断仪成功发送诊断报文请求之后到收到 ECU回复诊断响应的超时时间间隔 2&#xff09;P2 CAN_Server ECU 接收到诊断请求之后到开始发送诊断报文的时间间隔&#xff0c;一般默认最…

二维码门楼牌管理应用平台建设:场所检查的新模式

文章目录 前言一、二维码门楼牌管理应用平台的优势二、场所检查记录的重要性三、二维码门楼牌管理应用平台在场所检查中的应用四、二维码门楼牌管理应用平台的未来展望 前言 随着信息技术的飞速发展&#xff0c;二维码作为一种高效、便捷的信息识别方式&#xff0c;正逐渐渗透…

服务器数据恢复—存储硬盘坏道,指示灯亮黄色的数据恢复案例

服务器数据恢复环境&故障&#xff1a; 一台某品牌EqualLogic PS系列某型号存储&#xff0c;存储中有一组由16块SAS硬盘组建的RAID5磁盘阵列&#xff0c;RAID5上划分VMFS文件系统存放虚拟机文件。存储系统上层一共分了4个卷。 raid5阵列中磁盘出现故障&#xff0c;有2块硬盘…

二极管钳位型光伏逆变并网建模simulink仿真

整理了二极管钳位型光伏逆变并网建模simulink仿真&#xff0c;效果明显&#xff0c;附赠仿真报告。适合小白 二极管钳位型光伏逆变并网是将光伏发电系统中的直流电能转换为交流电能&#xff0c;并与电网连接。在此仿真中使用最大功率点追踪&#xff08;MPPT&#xff09;技术&a…

基于CANoe从零创建以太网诊断工程(2)—— TCP/IP Stack 配置的三种选项

&#x1f345; 我是蚂蚁小兵&#xff0c;专注于车载诊断领域&#xff0c;尤其擅长于对CANoe工具的使用&#x1f345; 寻找组织 &#xff0c;答疑解惑&#xff0c;摸鱼聊天&#xff0c;博客源码&#xff0c;点击加入&#x1f449;【相亲相爱一家人】&#x1f345; 玩转CANoe&…

微信第三方开放平台,实现代公众号保留排版样式和图片发布文章

大家好&#xff0c;我是小悟 要想实现代公众号发布文章的功能&#xff0c;就得接入富文本编辑器&#xff0c;市面上富文本编辑器有很多&#xff0c;轻量的、重量的都有。 从开发者的角度&#xff0c;自然把轻量作为第一选择&#xff0c;因为好对接&#xff0c;怎么方便怎么来…

在win下,python如何调用.so库

#撰写c代码 #通过gcc命令编译成.so库 gcc -shared -o ./lib/pointlib.so point.c #python调用.so库 #运行结果 觉得本文对你有用&#xff0c;麻烦点赞或关注或收藏&#xff0c;你的肯定是我创作的无限动力&#xff0c;谢谢&#xff01;&#xff01;&#xff01;

制作一个RISC-V的操作系统十四-任务同步和锁

文章目录 并发与同步临界区和锁锁死锁解决死锁自旋锁&#xff08;spin lock&#xff09;原子性问题原子操作实现amoswap.w.aq例子 另一种方法自旋锁的注意事项代码其他同步技术 并发与同步 控制流&#xff1a;可理解为任务或进程 中断也可以理解为一个切换到另一个任务&#…

C++智能指针详解

目录 一. 智能指针初识 1.1 什么是智能指针 1.2 智能指针历史历程 1.3 为什么需要智能指针 1.3.1 内存泄漏 1.3.2 防止内存泄漏 1.3.3 异常的重新捕获 二. 智能指针的原理与使用 2.1 智能指针的原理 2.2 智能指针的使用 2.3 智能指针的拷贝问题…

docker网络和模式

Docker使用Linux桥接&#xff0c;在宿主机虚拟一个Docker容器网桥(docker0)&#xff0c;Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址&#xff0c;称为container-IP&#xff0c;同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个…

mars3d开发过程中点击面图层飞行定位,设置俯仰角度后,layer.flyTo({没有生效的排查思路

mars3d开发过程中点击面图层飞行定位&#xff0c;设置俯仰角度后&#xff0c;layer.flyTo({没有生效的排查思路记录&#xff0c;给大家提供一下以后排查定位问题的方向 问题场景相关代码&#xff1a; 1.项目本身代码&#xff1a; 2.精简了关键性代码后&#xff0c;就可以去ge…

【博客经验分享】博客小白在CSDN是如何做到一周内涨粉1800的

&#x1f393;我&#xff08;异构算力老群群-CSDN博客&#xff09;是在今年3月份才开始写博客的&#xff0c;目的是做一个博士&#x1f393;期间的笔录&#xff1b;在CSDN这个技术分享与交流的平台&#x1f310;&#xff0c;我近期实现了一个令人振奋的成就——那就是一周内涨粉…

纯血鸿蒙APP实战开发——评论组件案例实现

介绍 评论组件在目前市面上的短视频app中是一种很常见的场景&#xff0c;本案例使用全局状态保留能力弹窗来实现评论组件。点击评论按钮弹出评论组件&#xff0c;点击空白处隐藏该组件&#xff0c;再次点击评论按钮则会恢复上一次浏览的组件状态。 效果图预览 使用说明 点击…

CUDA的基础知识

文章目录 数据精度CUDA概念线程&线程块&线程网络&计算核心GPU规格参数内存 GPU并行方式数据并行流水并行张量并行混合专家系统 数据精度 FP32 是单精度浮点数&#xff0c;用8bit 表示指数&#xff0c;23bit 表示小数&#xff1b;FP16 是半精度浮点数&#xff0c;用…

L1-041 寻找250

作者 陈越 单位 浙江大学 对方不想和你说话&#xff0c;并向你扔了一串数…… 而你必须从这一串数字中找到“250”这个高大上的感人数字。 输入格式&#xff1a; 输入在一行中给出不知道多少个绝对值不超过1000的整数&#xff0c;其中保证至少存在一个“250”。 输出格式&a…