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#/