【前言】
最近看过一些讲rest的文章,要么专业稍晦涩、要么易懂稍片面。目前新项目中需要用到rest架构风格,想试试看能不能讲清楚。
【名词解释】
rest: representational state transfer → 表述性状态转移 → 一种架构风格
restful: rest风格的web应用
【思路】
《Rest In Practice》书中列举了通往rest思想的几个阶段:
level 0 :普通的请求/响应模式,使用xml、json格式发送请求/接收响应,单纯的传递参数,把http当成是一个传输通道;
level 1 :体现了Restful第一个特征——面向资源。调用指定对象的某个方法并传递参数,把http当成是一个传输通道;
level 2 :把http当成是一种传输协议,使用了http动词,如:get、post、put、delete等,写法类似下面这样,
GET /rest/api/dogs 获取所有小狗狗
POST /rest/api/dogs 添加一个小狗狗
PUT /rest/api/dogs/:dog_id 修改一个小狗狗
DELETE /rest/api/dogs/:dog_id 删除一个小狗狗
通常项目实现到level2,就已经很restful了;
level3 :超媒体控制。思想貌似是在level2的基础上,给每个资源赋予了状态,在不同的状态下,允许进行的操作不一样。
【通过生活小片段介绍每个level】实际项目中只要符合其中一个level的特点,就算rest架构风格
场景:一帮姐妹逛街,口渴,刚好路旁有一家HEYTEA,于是开始点单
level 0式的点单:
MM:"服务员,你好,我要5杯少糖的松露可可"
{
"addOrder": {
"orderName": "Truffle coco",
"condition": "less sugar",
"num": "five"
}
}
服务员:"好的,请付款",返回订单号
{
"orderId": "20181025001"
}
MM:“让我先看下会员卡上的余额多少”
{
"queryBalance": {
"cardId": "12345678"
}
}
服务员:"好的",返回余额
{
"balance": "0"
}
MM:"哎呀,钱不够,算了先不要了",删除订单
{
"deleteOrder": {
"orderId": "20181025001"
}
}
level 1式的点单-面向资源:
HEYTEA店生意越来越好,来喝奶茶的人越来越多,店长决定对店员分工,分为两类,一类只负责点单、一类负责会员卡查询,于是 →
MM:"服务员,你好,我要5杯少糖的松露可可"
/orders
{
"addOrder": {
"orderName": "Truffle coco",
"condition": "less sugar",
"num": "five"
}
}
服务员:"好的,请付款",返回订单号
{
"orderId": "20181025001"
}
MM:“让我先看下会员卡上的余额多少”
/vipcards
{
"queryBalance": {
"cardId": "12345678"
}
}
服务员:"好的",返回余额
{
"balance": "0"
}
MM:"哎呀,钱不够,算了先不要了",删除订单
/orders
{
"deleteOrder": {
"orderId": "20181025001"
}
}
level 2式的点单-使用http动词:
HEYTEA店主觉得店员处理订单/会员卡业务时还是很慢,他发现处理订单的员工,每次都要去订单内容里看客户是点单还是取消订单,于是约定,
凡是点单的请求,都在请求上面写上“post”、
删除订单的,写上“delete”、
查询会员卡的,写上“get”、
修改订单的,写上“put”,于是 →
MM:"服务员,你好,我要5杯少糖的松露可可"
POST /orders
{
"orderName": "Truffle coco",
"condition": "less sugar",
"num": "five"
}
服务员:"好的,请付款",返回订单号
{
"orderId": "20181025001"
}
MM:“让我先看下会员卡上的余额多少”
GET /vipcards/12345678
服务员:"好的",返回余额
{
"balance": "0"
}
MM:"哎呀,钱不够,算了先不要了",删除订单
DELETE /orders/20181025001
level 3式的点单-给每个资源赋予状态:
有一天,一位小朋友买了一杯松露可可,但听见旁边尝过的MM说太甜了,所以想取消,但不知怎么取消,于是向店长抱怨门店没有直接提供取消订单的方法,因此店长决定再次更改请求的返回内容,就是在客户下单后,不仅给他们返回订单编号,还给客户返回所有可以对这个订单的操作,于是 →
boy:"服务员,你好,我要一杯松露可可"
POST /orders
{
"orderName": "Truffle coco",
"condition": "",
"num": "1"
}
服务员:"好的,请付款",返回订单号
{
"orderId": "20181025001",
"op": {
"rel": "delete",
"url": "/order/20181025001"
}
}
boy:"哎呀,太甜啦,算了先不要了",删除订单
DELETE /orders/20181025001
不知是否讲清楚了呢。