REST(英文:Representational State Transfer,简称REST)描述了一个架构样式的网络系统,好比 web 应用程序。它首次出如今 2000 年 Roy Fielding 的博士论文中,他是 HTTP 规范的主要编写者之一。在目前主流的三种Web服务交互方案中,REST相比于SOAP(Simple Object Access protocol,简单对象访问协议)以及XML-RPC更加简单明了,不管是对URL的处理仍是对Payload的编码,REST都倾向于用更加简单轻量的方法设计和实现。值得注意的是REST并无一个明确的标准,而更像是一种设计的风格。
经常使用的HTTP动词有下面五个(括号里是对应的SQL命令)。html
GET(SELECT) :从服务器取出资源(一项或多项)。
POST(CREATE):在服务器新建一个资源。
PUT(UPDATE) :在服务器更新资源(客户端提供改变后的完整资源)。
PATCH(UPDATE) :在服务器更新资源(客户端提供改变的属性)。
DELETE(DELETE):从服务器删除资源。
HEAD:获取资源的元数据。
OPTIONS:获取信息,关于资源的哪些属性是客户端能够改变的。java
该模型把 REST 服务按照成熟度划分红 4 个层次:git
API URI 设计最重要的一个原则: nouns (not verbs!) ,名词(而不是动词)。github
CRUD 简单例子:web
方法 | URL | 功能 |
---|---|---|
GET | /users | 获取用户列表 |
GET | /users/1 | 获取 id 为 1 的用户 |
POST | /users | 建立一个用户 |
PUT | /users/1 | 替换 id 为 1 的用户 |
PATCH | /users/1 | 修改 id 为 1 的用户 |
DELETE | /users/1 | 删除 id 为 1 的用户 |
上面是对某一种资源进行操做的 URI,那若是是有关联的资源,或者称为级联的资源,该如何设计 URI 呢?好比某一用户下的产品:spring
方法 | URL | 功能 |
---|---|---|
GET | /users/1/products | 获取 Id 为 1 用户下的产品列表 |
GET | /users/1/products/2 | 获取 Id 为 1 用户下 Id 为 2 的产品 |
POST | /users/1/products | 在 Id 为 1 用户下,建立一个产品 |
PUT | /users/1/products/2 | 在 Id 为 1 用户下,替换 Id 为 2 的产品 |
PATCH | /users/1/products/2 | 修改 Id 为 1 的用户下 Id 为 2 的产品 |
DELETE | /users/1/products/2 | 删除 Id 为 1 的用户下 Id 为 2 的产品 |
HAL(Hypertxt Application Language)是一个被普遍采用的超文本表达的规范。应用能够考虑遵循该规范。
规范事例(查询列表)以下:sql
{ "_links": { "self": { "href": "http://localhost:8080/lists" } }, "_embedded": { "lists": [ { "id": 1, "name": "Default", "_links": { "todo:items": { "href": "http://localhost:8080/lists/1/items" }, "self": { "href": "http://localhost:8080/lists/1" }, "curies": [ { "href": "http://www.midgetontoes.com/todolist/rels/{rel}", "name": "todo", "templated": true } ] } } ] } }
目前github提供的api就是这种风格。在返回结果中添加额外的信息(连接)以后,服务器端提供的表达能够帮助客户端更好的发现服务器端所支持的动做。数据库
在具体的表达中,应用虽然能够根据须要选择最适合的格式,可是在表达的基本结构上应该遵循必定的规范,这样能够保证最大程度的适用性。json
什么是Spring Data RESTapi
Spring Data REST是基于Spring Data的repository之上,能够把 repository 自动输出为REST资源,目前支持Spring Data JPA、Spring Data MongoDB、Spring Data Neo4j、Spring Data GemFire、Spring Data Cassandra的 repository 自动转换成REST服务,注意是自动。
简单点说,Spring Data REST把咱们须要编写的大量REST模版接口作了自动化实现,并符合HAL的规范.
本例子使用Jpa来实现数据库的操做,具体实现请点击 例子仓库查看
pom.xml加入
<!--Spring Data Rest--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-rest</artifactId> </dependency> <!--Spring Data Hal测试工具--> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-rest-hal-browser</artifactId> </dependency>
Product.java
package com.springboot.services.producer.jpa.entity.po; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import javax.persistence.*; @Data @Entity @Builder @NoArgsConstructor @AllArgsConstructor public class Product extends JpaBasePo { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false) private String name; @Column private String description; }
ProductMapper.java
package com.springboot.services.producer.jpa.dao; import com.springboot.services.producer.jpa.entity.po.Product; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.rest.core.annotation.RepositoryRestResource; @RepositoryRestResource public interface ProductMapper extends PagingAndSortingRepository<Product, Long> { }
spring: jpa: show-sql: true generate-ddl: true
就是这样咱们就已经提供了一个关于prodcut的rest api,简单的增、删、改、查都有了。连Controller都不用写,spring已经实现了。
启动命令:mvn springboot:run
curl -i -X GET http://localhost:9001/
站点首页列出了全部的api列表,目前一个products,为http://localhost:9001/products{?page,size,sort}
查询产品列表的url,客户端根据url导航就能够进一步的调用api。
http://localhost:9001/profile
能够获取api的原数据。
{ "_links" : { "products" : { "href" : "http://localhost:9001/products{?page,size,sort}", "templated" : true }, "profile" : { "href" : "http://localhost:9001/profile" } } }
curl -i -X GET http://localhost:9001/products
{ "_embedded" : { "products" : [ { "createdBy" : "system", "updatedBy" : "system", "createdTime" : "2018-07-22T23:40:38.288+0800", "updatedTime" : "2018-07-22T23:40:38.288+0800", "name" : "我是产品13111", "description" : "我是产品131的描述", "_links" : { "self" : { "href" : "http://localhost:9001/products/1" }, "product" : { "href" : "http://localhost:9001/products/1" } } },{}] }, "_links" : { "self" : { "href" : "http://localhost:9001/products{?page,size,sort}", "templated" : true }, "profile" : { "href" : "http://localhost:9001/profile/products" } }, "page" : { "size" : 20, "totalElements" : 16, "totalPages" : 1, "number" : 0 } }
curl -i -X GET http://localhost:9001/products/1
{ "createdBy" : "system", "updatedBy" : "system", "createdTime" : "2018-07-22T23:40:38.288+0800", "updatedTime" : "2018-07-22T23:40:38.288+0800", "name" : "我是产品13111", "description" : "我是产品131的描述", "_links" : { "self" : { "href" : "http://localhost:9001/products/0" }, "product" : { "href" : "http://localhost:9001/products/0" } } }
curl -i -X DELETE http://localhost:9001/products/0
curl -i -X PUT -H Content-Type:application/json -d '{"name":"产品1"}' http://localhost:9001/products/0
{ "createdBy" : "system", "updatedBy" : "system", "createdTime" : "2018-08-11T19:29:45.755+0800", "updatedTime" : "2018-08-11T19:29:45.755+0800", "name" : "产品1", "description" : null, "_links" : { "self" : { "href" : "http://localhost:9001/products/0" }, "product" : { "href" : "http://localhost:9001/products/0" } } }
curl -i -X POST -H Content-Type:application/json -d '{"name":"产品1"}' http://localhost:9001/products
{ "createdBy" : "system", "updatedBy" : "system", "createdTime" : "2018-08-11T19:24:33.072+0800", "updatedTime" : "2018-08-11T19:24:33.072+0800", "name" : "产品1", "description" : "desc", "_links" : { "self" : { "href" : "http://localhost:9001/products/10" }, "product" : { "href" : "http://localhost:9001/products/10" } } }
url:http://localhost:9001/browser/index.html#/