Java开发RESTful(一)概念入门
【原创文章,转载请注明原文章地址,谢谢!】
说明
新开一个专题,针对RESTful相关内容,从入门,到使用Java,主要是SpringMVC来完成RESTful开发。希望对刚接触RESTful的同学有所帮助
什么是RESTful
RESTful是代表REST化,或者说设计遵从REST架构。所以要了解RESTful就需要了解REST。而REST并不是一两句话能够简单说明清楚的,在本文中,尝试不要用那么高级的眼光去理解REST,而是放低身段,从实际的例子简单理解什么是REST。
简单理解REST
REST从字面上讲叫做Representational State Transfer,翻译成表现层状态转移,但是一般在翻译的时候,前面会加一个Resource,即Resource Representational State Transfer,即为资源表现层状态转移。
举一个简单的例子来阐述,比如一个优惠券功能,最基本需求:
- 后台能够设置优惠券类型
- 后台根据优惠券类型创建优惠券
- 前台用户查看优惠券类型列表
- 前台用户领取优惠券
- 前台用户使用优惠券
- 前台支持App和网页版本
不考虑具体的模型,单就请求路径来说,可能的路径如下:
- 后台能够设置优惠券类型(http://classes.wolfcode.cn/coupon_setting.do)
- 后台根据优惠券类型创建优惠券(http://classes.wolfcode.cn/coupon_create.do)
- 前台用户查看优惠券类型列表(http://classes.wolfcode.cn/coupon_list.do)
- 前台用户领取优惠券(http://classes.wolfcode.cn/coupon_fetch.do)
- 前台用户使用优惠券(http://classes.wolfcode.cn/coupon_using.do)
- 前台支持App和网页版本:针对App版本和网页版本,提交的数据,可能又不一样,比如App端需要使用Json传递数据,而网页版本可能只需要一个合成好的HTML代码片段。那么可能出现的情况就变为查看优惠券列表分为了两个地址:
http://classes.wolfcode.cn/coupon_list_json.do和http://classes.wolfcode.cn/coupon_list_html.do;或者使用一个参数来表示返回视图的类型:
http://classes.wolfcode.cn/coupon_list.do?view=json和http://classes.wolfcode.cn/coupon_list?view=html
至此,我们已经很清楚的看出来针对一个非常简单的需求,产生的问题:
- 针对每一个优惠券的操作,我们都需要一个独立的URL去操作,为什么?原因在于,我们对优惠券的动作需要反映在URL中;
- 如果有不同的响应方式,我们可能需要额外的参数,甚至不同的请求URL来描述;
- 请求参数包含在请求地址中,无法针对性做缓存;
- 会产生大量的URL,非常不方便接口的维护和文档的维护;
当然,这样做是完全可以的,目前也有大量的应用是使用这种方式来开发的。但是我相信,在了解和熟悉了REST之后,下一个项目,你一定不会使用这种方式开发了。
那马上进入REST。如果使用REST的概念来设计这样一个需求,又会是什么样的呢?(注意,下面我会直接列出一些REST的概念,重点看效果)。
首先在REST中,需要抽象出一个叫做资源的概念,简单理解,资源就是我们要操作的对象,使用URL表示。例如,针对优惠券我们就可以抽象出两个资源:优惠券类型和优惠券(优惠券是根据某个优惠券类型来生成的,比如京东的到店10元红包,这是一个优惠券类型,具体你在这个优惠券类型里面领到的那个红包,是这个优惠券类型生成的一个优惠券);
优惠券类型:http://classes.wolfcode.cn/couponSettings
优惠券:http://classes.wolfcode.cn/coupons
这两个资源对应的URL就固定下来,不会再变了,换句话说,我们所有的需求,都围绕这两个URL进行。
下面来看具体的操作:
-
后台能够设置优惠券类型
这个操作是针对优惠券类型来说的,并且相当于一个创建/修改的操作,在REST中,使用了:
POST http://classes.wolfcode.cn/couponSettings
PATCH http://classes.wolfcode.cn/couponSettings
就完成了优惠券类型的创建/修改操作。重点在POST和PATCH,我们以前比较常用的请求方式就两个,一个是POST,一个是GET,而在REST中,灵活的运用了HTTP协议中更多的请求方式,并给与了这些请求方式不同的含义。比如使用POST操作一个资源(URL),那么代表创建这个资源,如果使用PATCH操作一个资源(URL),那么代表修改这个资源。 -
前台用户查看优惠券类型列表
GET http://classes.wolfcode.cn/couponSettings
这就完成了优惠券列表的查看。可以猜到,GET代表的就是列出couponSettings(优惠券类型)这个资源。那么接着来看一个,比如我要查看某一个优惠券类型的具体明细呢?
GET http://classes.wolfcode.cn/couponSettings/1
应该能猜到了把,GET代表列出,但是这次在资源(优惠券类型)后面增加了一个1,那么这个1既是我们要查看的优惠券类型的id; -
后台根据优惠券类型创建优惠券
POST http://classes.wolfcode.cn/couponSettings/1/coupons
这个有点难以理解,首先基本资源是http://classes.wolfcode.cn/couponSettings,所以阅读为优惠券设置,其次,后面跟了一个1,那么就是id为1的优惠券设置,后面再跟了一个coupons,而coupons是优惠券,所以我们叫他二级资源,前面跟上一个POST,前面说了,POST代表创建,所以连起来阅读就是根据id为1的优惠券类型创建优惠券。
是不是已经有点感觉了? -
前台用户使用优惠券
这个很简单,关键是概念理解清楚,使用优惠券,既是把一个优惠券的状态从未使用变成已使用,所以对应的请求应该设计为:
PATCH http://classes.wolfcode.cn/coupons/1
即修改id为1(就是用户准备使用的这张优惠券)的状态,具体的状态的修改是通过POST参数完成的。 -
前台支持App和网页版本
最后来看看对不同响应类型的处理,这个也是REST非常有意思的点。我们不能通过资源来设置不同的响应类型,那通过什么告诉服务端呢?通过请求头。在请求头中有一个Accept type,这个指定这次请求需要接受什么类型,如果我们设置为text/html,那么服务器返回HTML片段即可,如果我们设置为application/json,那么服务器返回json即可。
怎么样?是不是完全没有去碰触资源的概念。
小结
通过上面的解释,我们简单来总结一波,什么叫REST?原意指表现层状态转移,我们今天只需要扩展一下这个概念,用人话讲,就是:客户端通过HTTP,对服务器端的资源进行操作,实现"表现层(使用HTTP动词去促使服务器端资源的)状态发生转化"。
PATCH http://classes.wolfcode.cn/coupons/1即:
客户端(浏览器)通过HTTP动作(PATCH)对服务器端的资源(id为1的coupons)进行操作,让这个资源的状态发生转变(从未使用变为已使用)!