REST 全稱是 Representational State Transfer,中文意思是表徵性狀態轉移。它首次出如今2000年Roy Fielding的博士論文中,Roy Fielding是HTTP規範的主要編寫者之一。值得注意的是REST並無一個明確的標準,而更像是一種設計的風格。若是一個架構符合REST的約束條件和原則,咱們就稱它爲RESTful架構。
理論上REST架構風格並非綁定在HTTP上,只不過目前HTTP是惟一與REST相關的實例。java
使用 HTTP 將 CRUD(create, retrieve, update, delete <建立、獲取、更新、刪除—增刪改查>)操做映射爲 HTTP 請求。若是按照HTTP方法的語義來暴露資源,那麼接口將會擁有安全性和冪等性的特性,例如GET和HEAD請求都是安全的, 不管請求多少次,都不會改變服務器狀態。而GET、HEAD、PUT和DELETE請求都是冪等的,不管對資源操做多少次, 結果老是同樣的,後面的請求並不會產生比第一次更多的影響。git
POST和PUT在建立資源的區別在於,所建立的資源的名稱(URI)是否由客戶端決定。 例如爲個人博文增長一個java的分類,生成的路徑就是分類名/categories/java,那麼就能夠採用PUT方法。不過不少人直接把POST、GET、PUT、DELETE直接對應上CRUD,例如在一個典型的rails實現的RESTful應用中就是這麼作的。web
狀態碼指示 HTTP 請求的結果:spring
HTTP頭中的 Accept 和 Content-Type 可用於描述HTTP請求中發送或請求的內容。若是客戶端請求JSON響應,那麼能夠將 Accept 設爲 application/json。相應地,若是發送的內容是XML,那麼能夠設置 Content-Type 爲 application/xml 。json
這裏介紹一些設計 REST API 的最佳實踐,你們先記住下面這句話:api
URL 是個句子,其中資源是名詞、HTTP 方法是動詞。
下面是一些例子:緩存
不要使用動詞:安全
客戶端和服務端都須要知道通訊所用的格式,這個格式要在 HTTP 頭中指定:服務器
使用 PUT, POST 和 DELETE 方法來改變狀態,不要使用 GET 方法來改變狀態:架構
若是一個資源與另外一個資源關聯,使用子資源:
再回顧一下這句話:
URL 是個句子,其中資源是名詞、HTTP 方法是動詞。
當客戶端經過API向服務端發起一個請求時,客戶端應當知道反饋:是否失敗、經過或者請求錯誤。HTTP 狀態碼是一批標準化代碼,在不一樣的場景下有不一樣的解釋。服務器應當老是返回正確的狀態碼。
下面是重要的HTTP代碼分類:
2xx (成功分類):這些狀態碼代碼請求動做被接收且被服務器成功處理。
3xx (轉發分類)
4xx (客戶端錯誤分類):這些狀態碼錶明客戶端提交了一個錯誤請求。
5xx (服務端錯誤分類)
你能夠遵循任何名稱規約,只要保持跨應用一致性便可。若是請求體和響應體是 JSON 類型,那麼請遵循駝峯名稱規約。
上面一些示例都是在一個數據集上的簡單查詢,對於複雜的數據,咱們須要在 GET 方法 API 上加一些參數來處理。下面是一些示例:
通常使用不帶點的簡單數字表示版本,數字前加字母v表明版本號,以下所示:
API 錯誤處理機制是很重要的,並且要好好規劃。極力推薦老是在返回字段中包含錯誤消息。一個 JSON 錯誤體應當爲開發者提供一些有用的信息:錯誤消息、錯誤代碼以及詳細描述。下面是一個較好的示例:
{ "code": 1234, "message": "Something bad happened :(", "description": "More details about the error here" }
推薦使用下面格式的 URL:
以下所示:
Spring Boot 提供了構建企業應用中 RESTful Web 服務的極佳支持。
要構建 RESTful Web 服務,咱們須要在構建配置文件中加上 Spring Boot Starter Web 依賴。
對於 Maven 用戶,使用如下的代碼在 pom.xml 文件中加入依賴:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
對於 Gradle 用戶,使用如下的代碼在 build.gradle 文件中加入依賴:
compile('org.springframework.boot:spring-boot-starter-web')
在繼續構建 RESTful web 服務前,建議你先要熟悉下面的註解:
@RestController 註解用於定義 RESTful web 服務。它提供 JSON、XML 和自定義響應。語法以下所示:
@RestController public class ProductServiceController { }
@RequestMapping 註解用於定義請求 URI 以訪問 REST 端點。咱們能夠定義 Request 方法來消費 produce 對象。默認的請求方法是 GET:
@RequestMapping(value = "/products") public ResponseEntity<Object> getProducts() { } Request Body @RequestBody 註解用於定義請求體內容類型。 public ResponseEntity<Object> createProduct(@RequestBody Product product) { }
@PathVariable 註解被用於定義自定義或動態的請求 URI,Path variable 被放在請求 URI 中的大括號內,以下所示:
public ResponseEntity<Object> updateProduct(@PathVariable("id") String id) { }
@RequestParam 註解被用於從請求 URL 中讀取請求參數。缺省狀況下是必須的,也能夠爲請求參數設置默認值。以下所示:
public ResponseEntity<Object> getProduct(
@RequestParam(value = "name", required = false, defaultValue = "honey") String name) {
}
下面的示例代碼定義了 HTTP GET 請求方法。在這個例子裏,咱們使用 HashMap 來在存儲 Product。注意咱們使用了 POJO 類來存儲產品。
在這裏,請求 URI 是 /products,它會從 HashMap 倉儲中返回產品列表。下面的控制器類文件包含了 GET 方法的 REST 端點:
package com.tutorialspoint.demo.controller; import java.util.HashMap; import java.util.Map; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.tutorialspoint.demo.model.Product; @RestController public class ProductServiceController { private static Map<String, Product> productRepo = new HashMap<>(); static { Product honey = new Product(); honey.setId("1"); honey.setName("Honey"); productRepo.put(honey.getId(), honey); Product almond = new Product(); almond.setId("2"); almond.setName("Almond"); productRepo.put(almond.getId(), almond); } @RequestMapping(value = "/products") public ResponseEntity<Object> getProduct() { return new ResponseEntity<>(productRepo.values(), HttpStatus.OK); } }
HTTP POST 請求用於建立資源。這個方法包含請求體。咱們能夠經過發送請求參數和路徑變量來定義自定義或動態 URL。
下面的示例代碼定義了 HTTP POST 請求方法。在這個例子中,咱們使用 HashMap 來存儲 Product,這裏產品是一個 POJO 類。
這裏,請求 URI 是 /products,在產品被存入 HashMap 倉儲後,它會返回字符串。
package com.tutorialspoint.demo.controller; import java.util.HashMap; import java.util.Map; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import com.tutorialspoint.demo.model.Product; @RestController public class ProductServiceController { private static Map<String, Product> productRepo = new HashMap<>(); @RequestMapping(value = "/products", method = RequestMethod.POST) public ResponseEntity<Object> createProduct(@RequestBody Product product) { productRepo.put(product.getId(), product); return new ResponseEntity<>("Product is created successfully", HttpStatus.CREATED); } }
HTTP PUT 請求用於更新已有的資源。這個方法包含請求體。咱們能夠經過發送請求參數和路徑變量來定義自定義或動態 URL。
下面的例子展現瞭如何定義 HTTP PUT 請求方法。在這個例子中,咱們使用 HashMap 更新現存的產品。此處,產品是一個 POJO 類。
這裏,請求 URI 是 /products/{id},在產品被存入 HashMap 倉儲後,它會返回字符串。注意咱們使用路徑變量 {id} 定義須要更新的產品 ID:
package com.tutorialspoint.demo.controller; import java.util.HashMap; import java.util.Map; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import com.tutorialspoint.demo.model.Product; @RestController public class ProductServiceController { private static Map<String, Product> productRepo = new HashMap<>(); @RequestMapping(value = "/products/{id}", method = RequestMethod.PUT) public ResponseEntity<Object> updateProduct(@PathVariable("id") String id, @RequestBody Product product) { productRepo.remove(id); product.setId(id); productRepo.put(id, product); return new ResponseEntity<>("Product is updated successsfully", HttpStatus.OK); } }
HTTP Delete 請求用於刪除存在的資源。這個方法不包含任何請求體。咱們能夠經過發送請求參數和路徑變量來定義自定義或動態 URL。
下面的例子展現如何定義 HTTP DELETE 請求方法。這個例子中,咱們使用 HashMap 來移除現存的產品,用 POJO 來表示。
請求 URI 是 /products/{id} 在產品被從 HashMap 倉儲中刪除後,它會返回字符串。 咱們使用路徑變量 {id} 來定義要被刪除的產品 ID。
package com.tutorialspoint.demo.controller; import java.util.HashMap; import java.util.Map; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import com.tutorialspoint.demo.model.Product; @RestController public class ProductServiceController { private static Map<String, Product> productRepo = new HashMap<>(); @RequestMapping(value = "/products/{id}", method = RequestMethod.DELETE) public ResponseEntity<Object> delete(@PathVariable("id") String id) { productRepo.remove(id); return new ResponseEntity<>("Product is deleted successsfully", HttpStatus.OK); } }