restful api的一些深层感悟
restful风格的api相当流行了,但很多开发人员对restful并没有深入理解,这几年面试了很多人,对restful的理解都很肤浅,好一点的也只知道统一资源接口,很多连表示层状态转移的涵义到底是什么,‘’转移‘’到底是什么意思都不知道。
相比远程过程调用(动词),restful的核心概念是资源(名词),大致可以对应领域驱动设计或领域模型中的领域实体,每个资源都有uri来标识。
restful介绍或restful api设计最佳实践网上资料已经很多了,例如什么是状态转移、uri中不要用动词或也不要带.do或.action等后缀、uri的可读性&层次性、http方法的幂等和安全等。
这里只提一些容易误解或不容易想明白的地方。
1)资源必须要有uri来标识,但一个资源可以有多个uri,它们都标识同一个资源。这个好理解,例如一个小朋友(资源),父母可以叫他小宝,也可叫他真实的名字,派出所还可以用他身份证号码来标识他。
2)运用restful风格来设计api,要有资源意识,要有名词意识。例如登录和注销(退出登录),它们是动词,显然不能直接映射到restful api的资源中,这是要想到这些动词关联的名词,我们可以想到对应的名词:会话(session)。put一个会话资源就是登录,delete一个会话就是注销。
3)实体或资源之间也存在聚合和包含关系,一对一、一对多、多对多关系。例如一个男人和女人结婚,这两个人存在婚姻关系。在restful中如何处理关系?restful风格中的核心概念是资源,既然要管理关系,那就要将关系作为一种资源,创建这种关系资源就建立了需要的关系,delete这个资源就是解除婚姻关系(离婚),所以婚姻关系也是种资源,也可用uri来标识它。至于婚姻关系是否是个核心概念,要看具体的应用,如果是在婚姻登记所的应用中,那婚姻关系肯定是核心,在一个个人档案管理系统中,可能并不关注婚姻关系,只是要在档案中填入配偶信息,那婚姻关系在这个应用的领域模型中就不需要存在。
4)http put和post的区别。put和post都可用来创建资源,此外put还可以更新资源。在创建资源时,put和post的区别是什么?put是创建一个具体的已知的资源,通常在uri中会包含有该资源的id,put的uri就是该资源的uri,也就是说客户端在创建资源时,客户端是知道该资源的uri的;而post是在资源集合(资源集合也是一种资源)中创建集合的一个成员(资源),post的uri是资源集合,客户端此时不知道该资源的uri,只知道资源集合的uri。
例如植树节在树林里植树,你拿着一棵树想亲自植树,此时可以用put /woods/{这颗树的id或唯一标识}来将这颗树种在树林里,例如put /woods/1 (省略http body),意思是栽颗id为1的树。你发多次put /woods/1请求种的是同一颗树(同一个资源),因此put是幂等的。如果是委托别人帮你种,你发出种树指令时不知道是种的那颗,此时用post /woods,意思是种棵树,在post的响应中会返回所种树的id或url(url中包含id)。发送多次post /woods请求,会种多棵树(不同的资源),因此post不是幂等的。当然你设计restful api时不遵守这些也是可以的,很多人的api中就用post(可能浏览器不支持PUT也是原因之一,但api一般是给后台系统调用),不用put,只要保证业务上不出错就行,例如业务上不重复。
5)对查询,除了可以将查询条件放在GET请求问号后的查询字符串中,对复杂查询或长度大的查询条件,还可以将查询条件放在GET或POST的http body中,Elasticsearch就是将查询条件放在GET或POST方法的body中。
6)restful风格不是银弹,不要手里拿着把锤子,看什么都像是钉子。