编写 Restful 风格的 API 接口正确姿势
qiyuwang 2024-11-26 08:03 9 浏览 0 评论
背景
目前微服务架构盛行,在了解了很多的实际微服务项目中,发现很多同时在设计业务 API 接口时,写法五花八门,现总结下目前项目上设计业务 API 接口的一些比较经典误区写法。
Restful 架构风格下,API 接口设计经典误区写法
1、查询某个对象接口:GET /app/getImportantApp
@GetMapping(path = "/getImportantApp")
public R getImportionApp(@RequestHeader("pid") String pid
2、查询列表接口:GET /app/list
@RequestMapping("/list")
public R list(String deptId)
3、保存对象接口:POST /app/save
@PostMapping("/save")
public R add(CmsAppLicationEntity appLication, String deptId)
4、删除对象接口:POST /app/delete
@DeleteMapping("/delete/{applicationId}")
public R delete(@PathVariable("applicationId") long applicationId)
5、更新对象接口:POST /app/batchUpdate
@PostMapping("/batchUpdate")
public R batchUpdate(@RequestBody List<CmsAppLicationEntity> list)
是不是感觉很熟悉的代码,难道写的不对?看着挺直观易懂的。如果采用 Restful 架构风格,上面这五种写法当然不对,这是对 Restful 架构风格不了解所致。
微信搜公众号「猿芯」,后台私信回复 1024 免费领取 SpringCloud、SpringBoot,微信小程序、Java面试、数据结构、算法等全套视频资料。
Restful 架构风格定义
“
Restful 是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
由于对 Restful 架构风格理解的不够透彻,一般会产生三种争议的设计误区。
- 误区一 请求路径 URI 是动词,而不是名词问题
- 误区二 URI中带版本号问题
- 误区三 URI 中路径大小写问题
误区一 请求路径 URI 是动词,而不是名词问题
按照对 Restful 架构风格理解,每个业务实体代表一种资源,代表一个名词。
比方说,设计产品列表接口时:
错误写法
/getProductList
请求路径 /getProductList 路径出现动词 get,这种写法是不对的。
推荐写法
/products
另外 URL 出现 /addProduct、/deleteProduct、/updateProduct 等写法也是不对的。
如果某些动作是 HTTP 动词表示不了的,你应该把该动作变成一种资源。
比方说,我们获取用户下的产品列表,错误接口设计是:
POST /users/1/getProducts
或者
POST /users/1/getProductList
正确的写法是把动词 getProducts 改成名词 products
POST /users/1/products
误区二 URI 中带版本号问题
业界对 URI 中是否带版本号存在三种说法。
第一种说法是,在请求路径中加入版本号,比方说:
POST /products/v1
GET /users/v1
POST /orders/v1
POST /items/v1
这种说法认为,在 URI 中加入版本避免了向后兼容,另外通过过期提示,重定向,文档等手段也能降低用户迁移到新的接口上的成本。
当然有人赞成在请求路径中加入版本号,也有人反对这种加版本号的做法,他们认为:
- 加入版本号会让服务接口变得混乱,经常碰到的情况是,一些低版本的API接口调用一些高版本的API接口,导致数据解析错误,这无疑加大了用户迁移的成本。
- 版本和资源的概念没有任何关系,因此在 URI 中加入版本会让用户混淆。
还有一种说法是,在路径中加版本号是错误的设计方式,在老外写的 Versioning REST Services 这篇文章指出,你应该在请求头的 Accept 指定你的版本号,而不是请求路径中。
例如:
For example, for versions 1.0, 1.1, and 2.0 of the foo data type as JSON set the Accept/Content-Type header as follows:
1.0: vnd.example-com.foo+json; version=1.0
1.1: vnd.example-com.foo+json; version=1.1
2.0: vnd.example-com.foo+json; version=2.0
前端 js 在请求头 Accept 指定 vnd.example-com.foo+json; version=1.1 的版本 version=1.1。
$.ajax({
beforeSend: function (req) {
req.setRequestHeader("Accept", "vnd.example-com.foo+json; version=1.1");
},
type: "GET",
url: "http://http://www.example.com/foo/12",
success: function (data) {
/* code elided */
},
dataType: "json"
});
我个人是比较倾向请求路径中加版本号的,因为我认为加版本号是站在程序角度来考虑新老版本的接口移植问题,特别是现在流行微服务架构,业务粒度很细的情况下,接口的升级,原有版本是否保留呢?
微信搜公众号「猿芯」,后台私信回复 1024 免费领取 SpringCloud、SpringBoot,微信小程序、Java面试、数据结构、算法等全套视频资料。
那什么时候该加版本号呢?
“
如果你开发的 restful 接口是开放的,你也不知道都有谁调用过,那么这个时候版本号就是必须的了。以百度地图接口为例,百度发布了 restful 风格的地图接口在网上,全国甚至全世界各行各业都可以调用这些接口,百度要对接口进行升级,该怎么办?如果百度直接在原有的url上进行升级,会产生什么样的结果呢?不可预估。程序员:老板,咱们的产品崩溃了!老板:为啥?程序员:百度升级了接口!哪怕仅仅是多返回了一个字段,都可能导致调用者原有的代码出现问题,毕竟百度无法知道所有人都是怎么解析返回值的。这个时候最好的做法就是加版本号,保持原有版本,发布新的版本,所有问题迎刃而解。老用户也不用因为百度的升级,进行代码的更新,新用户又能享受最新的接口,完美。
判断是否要加版本号的方法:
- 是否明确的知道都有谁调用了你的接口,并且能通知到,如果能,那可以不加版本号;
- restful接口升级的时候,原有版本是否保留,如果不保留,可以不加版本号;
当然,加版本号是有一定技巧的,版本号应该放在一个功能模块的后面,甚至一个 url就应该自己独立的版本,如 api/user/v2,这样调用者就不会有整套接口都升级到 v2的错觉。
误区三 URI 中路径大小写问题
URL 中路径最好是小写,不要有驼峰式写法,比如下面接口错误写法
POST /orderItems/v1/1001
推荐写法
POST /orders/v1/items/1001
或者
/order-items/v1/1001
总结
我见过很多采用基于微服务架构编写的微服务代码,大多数接口看似 restful 风格,然而仔细辨识才发现,原来是一堆的伪 restful 接口,要么动词名词不分,要么路径版本各种混乱。
实际上的场景是,restful 风格基本上停留在口口相传上,看起来逼格很高的东西也只能高高供起。大部分的程序员为了赶进度,完成 KPI,那还顾得上这种规范,一直在疯狂的打码中。
附录1 API 设计风格基本规则
- 使用名词而不是动词
不要使用:
/getAllUsers
/createNewUser
/deleteAllUser
- Get 方法和查询参数不应该涉及状态改变
使用 PUT, POST 和 DELETE 方法 而不是 GET 方法来改变状态,不要使用 GET 进行状态改变:
- 使用复数名词
不要混淆名词单数和复数,为了保持简单,只对所有资源使用复数。
/cars 而不是 /car
/users 而不是 /user
/products 而不是 /product
/settings 而部署 /setting
- 使用子资源表达关系 如果一个资源与另外一个资源有关系,使用子资源:
GET /cars/711/drivers/ 返回 car 711的所有司机
GET /cars/711/drivers/4 返回 car 711的4号司机
- 使用 Http 头声明序列化格式
在客户端和服务端,双方都要知道通讯的格式,格式在 HTTP-Header 中指定
Content-Type 定义请求格式
Accept 定义系列可接受的响应格式
- 为集合提供过滤 排序 选择和分页等功能
Filtering 过滤: 使用唯一的查询参数进行过滤:
GET /cars?color=red 返回红色的cars
GET /cars?seats<=2 返回小于两座位的cars集合
Sorting 排序:允许针对多个字段排序
GET /cars?sort=-manufactorer,+model
这是返回根据生产者降序和模型升序排列的 car 集合。
移动端能够显示其中一些字段,它们其实不需要一个资源的所有字段,给 API 消费者一个选择字段的能力,这会降低网络流量,提高 API 可用性。
GET /cars?fields=manufacturer,model,id,color
Paging 分页,使用 limit 和 offset.实现分页,缺省 limit=20 和 offset=0;
GET /cars?offset=10&limit=5
为了将总数发给客户端,使用订制的 HTTP 头:X-Total-Count。链接到下一页或上一页可以在 HTTP 头的 link 规定,遵循 Link 规定:
Link: <https://blog.mwaysolutions.com/sample/api/v1/cars?offset=15&limit=5>; rel="next",
<https://blog.mwaysolutions.com/sample/api/v1/cars?offset=50&limit=3>; rel="last",
<https://blog.mwaysolutions.com/sample/api/v1/cars?offset=0&limit=5>; rel="first",
<https://blog.mwaysolutions.com/sample/api/v1/cars?offset=5&limit=5>; rel="prev",
- 版本化你的 API
使得 API 版本变得强制性,不要发布无版本的 API,使用简单数字,避免小数点如 2.5
一般在 Url 后面使用 ?v
/blog/api/v1
- 使用 Http 状态码处理错误
如果你的API没有错误处理是很难的,只是返回 500 和出错堆栈不一定有用,Http 状态码提供 70 个出错,我们只要使用 10 个左右:
200 – OK – 一切正常
201 – OK – 新的资源已经成功创建
204 – OK – 资源已经成功擅长
304 – Not Modified – 客户端使用缓存数据
400 – Bad Request – 请求无效,需要附加细节解释如 "JSON无效"
401 – Unauthorized – 请求需要用户验证
403 – Forbidden – 服务器已经理解了请求,但是拒绝服务或这种请求的访问是不允许的。
404 – Not found – 没有发现该资源
422 – Unprocessable Entity – 只有服务器不能处理实体时使用,比如图像不能被格式化,或者重要字段丢失。
500 – Internal Server Error – API开发者应该避免这种错误。
使用详细的错误包装错误:
{
"errors": [
{
"userMessage": "Sorry, the requested resource does not exist",
"internalMessage": "No car found in the database"
"code": 34,
"more info": "http://dev.mwaysolutions.com/blog/api/v1/errors/12345"
}
]
}
- 允许覆盖http方法
一些代理只支持 POST 和 GET 方法, 为了使用这些有限方法支持 RESTful API,需要一种办法覆盖 http 原来的方法。使用订制的 HTTP 头 X-HTTP-Method-Override 来覆盖 POST 方法.
附录2 HTTP协议常用的动词说明
动词描述GET查询列表或者单个对象的时候使用POST一般是提交表单或者是查询参数比较多的时候使用PUT更新资源的时候使用DELETE删除资源的时候使用
参考
- https://blog.csdn.net/suo082407128/article/details/60132447
- http://www.ruanyifeng.com/blog/2011/09/restful.html
- https://www.informit.com/articles/article.aspx?p=1566460
- https://blog.csdn.net/qq_27026603/article/details/82012277
后台私信回复 1024 免费领取 SpringCloud、SpringBoot,微信小程序、Java面试、数据结构、算法等全套视频资料。
相关推荐
- 微软宣布将于10月份关闭OneDrive组功能
-
【巴士数码】微软已经宣布将在今年10月关闭OneDrive的组功能。一年多之前,微软已经关闭了用户在OneDrive当中创建组的功能。大大多数用户会发现共享文件夹是一种合适的替代品,而且由于这一点,O...
- 玩转Win10任务栏:从基础设置到效率神器的全攻略
-
一、基础操作:解锁任务栏的「隐藏布局」...
- 文档以只读模式打开的原因及解决方法
-
当文档以只读模式打开时,可能由多种原因导致。以下是详细的原因分析与对应解决方法,您可根据实际情况灵活选择操作。一、文件属性设置问题(一)Windows系统在Windows系统中,若文件属性被标记...
- Windows系统的优化(windows优化设置)
-
今天给大家讲一讲系统的图标和一些基本的优化。安装了原版系统之后有很多地方需要优化比如桌面图标小箭头,盾牌,休眠占用内存,关闭通知栏。首先我们打开软件这款软件以前就讲到过就是dism++软件,他可以清理...
- Win 10偷偷传送用户隐私至微软(win10设备隐私)
-
自推出以来Win10不断被揭发盗取用户带宽、泄漏WiFi密码等各式各样的私隐问题,令不少网络专家开始留意Win10还隐藏了多少类似的私隐漏洞。最近再有人发现Win10部分功能静静...
- OneDrive逆势下调存储空间,不限量存储被取消
-
日前,微软在周一晚发布的博客文章中表示,由于部分用户存滥用储存功能,所以该公司将取消不限量OneDrive存储服务。不限量用户的最大存储空间将被下调至1TB,定价为6.99美元,对于已存储较多文件和内...
- Win10中那些被微软取消的功能(微软公司从9日起停止对windows8的主流服务支持)
-
很多用户在使用Win10的时候,都会发现一些在Win7系统中的功能被取消了,有的时候想找也找不到。那么到底是那些过去的功能在Win10中被取消了呢?下面我们就简单梳理一下,并且告诉大家解决的办法。Wi...
- 微软推Win11 Dev 26200.5570预览版:语音打字上线脏话过滤选项
-
IT之家4月26日消息,微软公司昨日(4月25日)发布博文,邀请Dev频道的WindowsInsider项目成员,测试适用于Windows1124H2的KB50556...
- 微软VSCode商店发现9款挖矿恶意插件,已安装超30万次
-
IT之家4月8日消息,科技媒体bleepingcomputer昨日(4月7日)发布博文,报道称安全专家在微软VSCode扩展商店中,发现了9款伪装成开发工具的恶意插件。这些插...
- 微软Windows 11开始菜单大改版!(windows 11 开始菜单)
-
根据最新消息,微软正在对Windows11的开始菜单进行重大改版,这一更新将彻底改变其布局和功能。Windows11的开始菜单将从现有的多栏布局改为单栏可滚动视图,所有固定图标和已安装应用都将集中...
- OneDrive无限存储空间取消 免费降至5GB
-
2015-11-0313:35:06作者:徐鹏北京时间11月3日消息,微软在一篇博客文章中称,将取消OneDrive存储服务的不限量空间,原因是部分用户有滥用问题。OneDrive无限存储空间取消...
- 省出电脑C盘空间!微软悄悄更新:OneDrive终于能卸载了
-
快科技3月12日消息,近日,微软悄悄地在官方更新了关闭、禁用、卸载Windows自带软件OneDrive的方法。微软Windows系统自带了很多软件和功能,其中有很多我们可能永远都用不上。但这些软件还...
- 微软关闭OneDrive新建组群功能(windows关闭onedrive)
-
微软的OneDrive云端储存服务能够让你创建组群(Group),这样当你和团队成员共同从事一个项目的时候能够通过云端协作提升效率,并且组群的文档储存空间还将同你标准的OneDrive分割独立开来。不...
- 微软为何取消OneDrive无限制容量存储?被75TB占用吓坏
-
那么为什么微软会取消Office365的无限OneDrive存储呢?“自推出Office365订阅无限制存储服务以来,一小部分用户开始备份多台PC设备,存储众多电影收藏合集和DVR录像。在某些情况下...
- Win11必关的5个设置!关闭后电脑流畅到起飞,操作简单不藏私!
-
Windows11虽然界面炫酷,但默认设置中隐藏了不少“拖慢电脑”的坑!尤其是老电脑用户,用久了卡顿、开机慢、反应迟钝……其实只需关闭几个鸡肋功能,就能让电脑提速50%以上!...
你 发表评论:
欢迎- 一周热门
- 最近发表
-
- 微软宣布将于10月份关闭OneDrive组功能
- 玩转Win10任务栏:从基础设置到效率神器的全攻略
- 文档以只读模式打开的原因及解决方法
- Windows系统的优化(windows优化设置)
- Win 10偷偷传送用户隐私至微软(win10设备隐私)
- OneDrive逆势下调存储空间,不限量存储被取消
- Win10中那些被微软取消的功能(微软公司从9日起停止对windows8的主流服务支持)
- 微软推Win11 Dev 26200.5570预览版:语音打字上线脏话过滤选项
- 微软VSCode商店发现9款挖矿恶意插件,已安装超30万次
- 微软Windows 11开始菜单大改版!(windows 11 开始菜单)
- 标签列表
-
- navicat无法连接mysql服务器 (65)
- 下横线怎么打 (71)
- flash插件怎么安装 (60)
- lol体验服怎么进 (66)
- ae插件怎么安装 (62)
- yum卸载 (75)
- .key文件 (63)
- cad一打开就致命错误是怎么回事 (61)
- rpm文件怎么安装 (66)
- linux取消挂载 (81)
- ie代理配置错误 (61)
- ajax error (67)
- centos7 重启网络 (67)
- centos6下载 (58)
- mysql 外网访问权限 (69)
- centos查看内核版本 (61)
- ps错误16 (66)
- nodejs读取json文件 (64)
- centos7 1810 (59)
- 加载com加载项时运行错误 (67)
- php打乱数组顺序 (68)
- cad安装失败怎么解决 (58)
- 因文件头错误而不能打开怎么解决 (68)
- js判断字符串为空 (62)
- centos查看端口 (64)