关于REST

我不擅长恋爱,但我天生爱你。 --zhu
前言
1、WEB API两种风格:面向过程(RPC)、面向REST(REST)
2、RPC:“控制器/操作方法”的形式把服务器端的代码当成方法去调用。把HTTP当成传输数据的通道,不甘心HTTP谓词。通过QueryString、请求报文给服务器传递数据,状态码。比如:/Persons/GetAll、/Persons/GetById?id=8、/Persons/Update、/Persons/DeleteById/8

REST
按照HTTP的语义来使用HTTP协议。
1、URL用于资源的定位:/user/888、/user/888/orders;
2、HTTP谓词:GET,POST(新增),PUT(整体更新),DELETE, PATCH(局部更新)等;
3、什么是“幂等”,例:DELETE,PUT,GET是幂等的,POST不幂等。
4、GET的响应可以被缓存。
5、服务器端要通过状态码来反映资源获取的结果:404、403(没有权限)、201(新增成功)。

对比
RPC:业务驱动,自然,高效。
REST:要求开发人员对REST原则更了解、并且有更多的设计能力。

REST优点
1、通过URL对资源定位,语义更清晰。
2、通过HTTP谓词表示不同的操作,接口自描述。
3、可以对GET,PUT,DELETE请求进行测试。
4、可以用GET请求做缓存,提高响应速度。
5、通过HTTP状态码反映服务器端的处理结果,统一错误处理机制。

REST缺点
1、真实系统的资源非常复杂,很难清晰地进行资源划分,对技术人员的业务水平要求高。
2、不是所有的操作都能简单地对应确定的HTTP谓词中。
3、系统的进化可能会改变幂等性。
4、通过URL进行资源定位不符合中文用户的习惯。
5、HTTP状态码个数有限。
6、有些环节会篡改非200响应码的响应报文。
7、有的客户端不支持PUT,DELETE请求。

如何选择
1、REST是学术化概念,仅供参考。AWS,ES比较RESTful,阿里、腾讯却也有很多不RESTful。
2、根据公司情况,进行REST的选择和裁剪。

HTTP传递参数的三种方式
URL:适合定位;长度限制。 /user/delete
QueryString:灵活;长度限制。 /user?name=tom&age=18
请求报文体:灵活;长度不限制;不支持GET,DELETE。

三种方式的不同语义
URL:资源定位。
QueryString:URL之外的额外数据。
请求报文体:供PUT、POST提供数据。

实施指南
1、对于保存、更新这些请求POST、PUT请求,把全部参数都放到请求报文中。
2、对于DELETE请求,要传递的参数就是一个资源的id,因此把参数放到QueryString中即可。
3、对于GET请求,一般参数的内容都不会太长,因此统一通过QueryString传递参数即可。对于可能参数内容超过URL限制的请求,由于GET、PUT请求都是幂等的,因此我们把请求改成通过PUT请求,然后通过报文体来传递参数。

状态码
1、REST:通过HTTP状态码返回服务器的处理结果。
2、问题:
1)HTTP状态码数量有限;
2)HTTP状态码并不适合用来表示业务层面的错误码,它是一个用来表示技术层面信息的状态码。新增用户的操作中,如果服务器要求Json格式,客户端提交XML,服务器返回400是没问题的。但是如果用户名格式错误,或者用户名重复,存在200派和400派。
对于400(谷歌等):
1)网关等可以监控HTTP状态码,如果接口频繁出现4xx状态码,那么就说明客户端代码不完善。
2)很多系统都是按照HTTP状态码的不同含义进行设计的。如果失败了服务器端返回状态码还是200的话,违背软件设计初衷。
对于200(百度等):
网络问题归网络,业务问题归业务。业务错误不应该和技术错误混在一起。把系统日志和业务日志区分开。

倾向400
1、对于数据库服务器连接失败、请求报文格式、服务器端异常等非业务错误,服务器端应该返回4xx、5xx等状态码。
2、对于业务层面的错误,比如用户不存在,我们要使用4xx等HTTP状态码返回。同样在响应报文体给出详细的错误详细,比如{"code":3,"message":"用户不存在"}。
3、不仅要返回4xx的HTTP状态码,而且不要忘了通过响应报文体给出详细错误信息。对于用户不存在,不仅要404,而且把响应报文体设置为{"code":3,"message":"用户已存在"},这样区分问题所在。

落地指南
1、使用RPC风格:Users/AddNew、Users/GetAll、Users/DeleteById.
2、对于可以缓存的操作,使用GET请求;对于幂等的更新操作,使用PUT请求;对于幂等的删除操作,使用DELETE请求;对于其他操作,统一使用POST请求。
3、参数:保存、更新类的请求使用POST、PUT请求,把全部参数放到请求报文体;对于GET和DELETE请求,把参数放到QueryString中。推荐使用URL做资源定位。
4、对于业务错误,服务器端返回适合的4xx状态码,不知道该选择哪个状态码就用400;在报文体中通过code参数提供业务错误以及错误消息。

实现技术
1、控制器上[Route("[controller]/[action]")]
2、强制要求控制器中不同的操作用不同的方法名
3、把[HttpGet]、[HttpPost]、[HttpDelete]、[HttpPut]等添加到对应的操作方法上。
4、如果控制器存在方法没有添加[HttpGet]、[HttpPost]等的public方法,Swagger就会报错,可以用[ApiExplorerSettings(IgnoreApi=true)]

posted @ 2024-07-23 22:14  小脑虎爱学习  阅读(6)  评论(0编辑  收藏  举报