最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

搭建 Restful Web 服務(wù)

2022-03-09 11:05 作者:信碼由韁  | 我要投稿

1. 理解 REST

??REST 全稱(chēng)是 Representational State Transfer,中文意思是表征性狀態(tài)轉(zhuǎn)移。它首次出現(xiàn)在2000年Roy Fielding的博士論文中,Roy Fielding是HTTP規(guī)范的主要編寫(xiě)者之一。值得注意的是REST并沒(méi)有一個(gè)明確的標(biāo)準(zhǔn),而更像是一種設(shè)計(jì)的風(fēng)格。如果一個(gè)架構(gòu)符合REST的約束條件和原則,我們就稱(chēng)它為RESTful架構(gòu)。


1.1. REST 原則

  • 資源 可通過(guò)目錄結(jié)構(gòu)樣式的 URIs 暴露

  • 表述 可以通過(guò) JSON 或 XML 表達(dá)的數(shù)據(jù)對(duì)象或?qū)傩詠?lái)傳遞

  • 消息 使用統(tǒng)一的 HTTP 方法(例如:GET、POST、PUT 和 DELETE)

  • 無(wú)狀態(tài) 客戶(hù)端與服務(wù)端之間的交互在請(qǐng)求之間是無(wú)狀態(tài)的,從客戶(hù)端到服務(wù)端的每個(gè)請(qǐng)求都必須包含理解請(qǐng)求所必需的信息

1.2. HTTP 方法

??使用 HTTP 將 CRUD(create, retrieve, update, delete <創(chuàng)建、獲取、更新、刪除—增刪改查>)操作映射為 HTTP 請(qǐng)求。如果按照HTTP方法的語(yǔ)義來(lái)暴露資源,那么接口將會(huì)擁有安全性和冪等性的特性,例如GET和HEAD請(qǐng)求都是安全的, 無(wú)論請(qǐng)求多少次,都不會(huì)改變服務(wù)器狀態(tài)。而GET、HEAD、PUT和DELETE請(qǐng)求都是冪等的,無(wú)論對(duì)資源操作多少次, 結(jié)果總是一樣的,后面的請(qǐng)求并不會(huì)產(chǎn)生比第一次更多的影響。

1.2.1. GET

  • 安全且冪等

  • 獲取信息

1.2.2. POST

  • 不安全且不冪等

  • 使用請(qǐng)求中提供的實(shí)體執(zhí)行操作,可用于創(chuàng)建資源或更新資源

1.2.3. PUT

  • 不安全但冪等

  • 使用請(qǐng)求中提供的實(shí)體執(zhí)行操作,可用于創(chuàng)建資源或更新資源

1.2.4. DELETE

  • 不安全但冪等

  • 刪除資源

    ??POST和PUT在創(chuàng)建資源的區(qū)別在于,所創(chuàng)建的資源的名稱(chēng)(URI)是否由客戶(hù)端決定。 例如為我的博文增加一個(gè)java的分類(lèi),生成的路徑就是分類(lèi)名/categories/java,那么就可以采用PUT方法。不過(guò)很多人直接把POST、GET、PUT、DELETE直接對(duì)應(yīng)上CRUD,例如在一個(gè)典型的rails實(shí)現(xiàn)的RESTful應(yīng)用中就是這么做的。

1.3. HTTP status codes

??狀態(tài)碼指示 HTTP 請(qǐng)求的結(jié)果:

  • 1XX:信息

  • 2XX:成功

  • 3XX:轉(zhuǎn)發(fā)

  • 4XX:客戶(hù)端錯(cuò)誤

  • 5XX:服務(wù)端錯(cuò)誤

1.4. 媒體類(lèi)型

??HTTP頭中的 Accept 和 Content-Type 可用于描述HTTP請(qǐng)求中發(fā)送或請(qǐng)求的內(nèi)容。如果客戶(hù)端請(qǐng)求JSON響應(yīng),那么可以將 Accept 設(shè)為 application/json。相應(yīng)地,如果發(fā)送的內(nèi)容是XML,那么可以設(shè)置 Content-Type 為 application/xml 。

2. REST API 設(shè)計(jì)最佳實(shí)踐

??這里介紹一些設(shè)計(jì) REST API 的最佳實(shí)踐,大家先記住下面這句話(huà):

URL 是個(gè)句子,其中資源是名詞、HTTP 方法是動(dòng)詞。

2.1. 使用名詞來(lái)表示資源

??下面是一些例子:

  • GET - /users:返回用戶(hù)列表

  • GET - /users/100:返回一個(gè)特定用戶(hù)

  • POST - /users:創(chuàng)建一個(gè)新用戶(hù)

  • PUT - /users/200:更新一個(gè)特定用戶(hù)

  • DELETE - /users/711:刪除一個(gè)特定用戶(hù)

    ??不要使用動(dòng)詞:

  • /getAllsers

  • /getUserById

  • /createNewUser

  • /updateUser

  • /deleteUser

2.2 在 HTTP 頭中使用適當(dāng)?shù)男蛄谢袷?/h1>

??客戶(hù)端和服務(wù)端都需要知道通信所用的格式,這個(gè)格式要在 HTTP 頭中指定:

  • Content-Type?定義請(qǐng)求格式

  • Accept?定義一個(gè)可接受的響應(yīng)格式列表

2.3 Get 方法和查詢(xún)參數(shù)不應(yīng)當(dāng)改變狀態(tài)

??使用 PUT, POST 和 DELETE 方法來(lái)改變狀態(tài),不要使用 GET 方法來(lái)改變狀態(tài):

  • GET?/users/711?activate?或

  • GET?/users/711/activate

2.4. 使用子資源表示關(guān)聯(lián)

??如果一個(gè)資源與另一個(gè)資源關(guān)聯(lián),使用子資源:

  • GET /cars/711/drivers/ 返回711號(hào)汽車(chē)的駕駛員列表

  • GET /cars/711/drivers/4 返回711號(hào)汽車(chē)的第4號(hào)駕駛員

2.5. 使用適當(dāng)?shù)?HTTP 方法 (動(dòng)詞)

??再回顧一下這句話(huà):

URL 是個(gè)句子,其中資源是名詞、HTTP 方法是動(dòng)詞。

  • GET:獲取在URI資源中指定的表述,響應(yīng)消息體包含所請(qǐng)求資源的細(xì)節(jié)。

  • POST:創(chuàng)建一個(gè)URI指定的新資源,請(qǐng)求消息體提供新資源的細(xì)節(jié)。注意,POST也可以觸發(fā)一些操作,而不一定是要?jiǎng)?chuàng)建新資源。

  • PUT:創(chuàng)建或替代指定URI的資源。請(qǐng)求消息體指定要?jiǎng)?chuàng)建或更新的資源。

  • DELETE:移除指定URI的資源。

2.6. HTTP 響應(yīng)狀態(tài)碼


??當(dāng)客戶(hù)端通過(guò)API向服務(wù)端發(fā)起一個(gè)請(qǐng)求時(shí),客戶(hù)端應(yīng)當(dāng)知道反饋:是否失敗、通過(guò)或者請(qǐng)求錯(cuò)誤。HTTP 狀態(tài)碼是一批標(biāo)準(zhǔn)化代碼,在不同的場(chǎng)景下有不同的解釋。服務(wù)器應(yīng)當(dāng)總是返回正確的狀態(tài)碼。

??下面是重要的HTTP代碼分類(lèi):


  • 2xx (成功分類(lèi)):這些狀態(tài)碼代碼請(qǐng)求動(dòng)作被接收且被服務(wù)器成功處理。200:Ok 表示 GET、PUT 或 POST 請(qǐng)求的標(biāo)準(zhǔn)狀態(tài)碼。201:Created(已創(chuàng)建)表示實(shí)例已被創(chuàng)建,多用于 POST 方法。204:No Content(無(wú)內(nèi)容)表示請(qǐng)求已被成功處理但沒(méi)有返回任何內(nèi)容。常用于 DELETE 方法返回。

  • 3xx (轉(zhuǎn)發(fā)分類(lèi))304:Not Modified(無(wú)修改)表示客戶(hù)端已經(jīng)緩存此響應(yīng),無(wú)須再次傳輸相同內(nèi)容。

  • 4xx (客戶(hù)端錯(cuò)誤分類(lèi)):這些狀態(tài)碼代表客戶(hù)端提交了一個(gè)錯(cuò)誤請(qǐng)求。400:Bad Request(錯(cuò)誤請(qǐng)求)表示客戶(hù)端請(qǐng)求沒(méi)被處理,因?yàn)榉?wù)端無(wú)法理解客戶(hù)端請(qǐng)求。401:Unauthorized(無(wú)授權(quán))表示客戶(hù)端無(wú)權(quán)訪(fǎng)問(wèn)資源,應(yīng)當(dāng)加上所需的認(rèn)證信息后再次請(qǐng)求。403:Forbidden(禁止訪(fǎng)問(wèn))表示請(qǐng)求有效且客戶(hù)端已獲授權(quán),但客戶(hù)端無(wú)權(quán)訪(fǎng)問(wèn)該資源。404:Not Found(沒(méi)發(fā)現(xiàn))表示所請(qǐng)求的資源現(xiàn)在不可用。410:Gone(移除)表示所請(qǐng)求的資源已被移除。

  • 5xx (服務(wù)端錯(cuò)誤分類(lèi))500:Internal Server Error(內(nèi)部服務(wù)器錯(cuò)誤)表示請(qǐng)求有效,但是服務(wù)端發(fā)生了異常。503:Service Unavailable(服務(wù)不可用)表示服務(wù)器關(guān)閉或不可用,通常是指服務(wù)器處于維護(hù)狀態(tài)。

2.7. 名稱(chēng)規(guī)約

??你可以遵循任何名稱(chēng)規(guī)約,只要保持跨應(yīng)用一致性即可。如果請(qǐng)求體和響應(yīng)體是 JSON 類(lèi)型,那么請(qǐng)遵循駝峰名稱(chēng)規(guī)約。

2.8. 搜索、排序、過(guò)濾與分頁(yè)

??上面一些示例都是在一個(gè)數(shù)據(jù)集上的簡(jiǎn)單查詢(xún),對(duì)于復(fù)雜的數(shù)據(jù),我們需要在 GET 方法 API 上加一些參數(shù)來(lái)處理。下面是一些示例:

  • 排序:這個(gè)例子中,客戶(hù)想獲取排序的公司列表,GET /companies 應(yīng)當(dāng)在查詢(xún)時(shí)接受多種排序參數(shù)。譬如 GET /companies?sort=rank_asc 將以等級(jí)升序的方式對(duì)公司進(jìn)行排序。

  • 過(guò)濾:要過(guò)濾數(shù)據(jù)集,我們可以通過(guò)查詢(xún)參數(shù)傳遞不同的選項(xiàng)。比如 GET /companies?category=banking&location=india 將過(guò)濾分類(lèi)為銀行且位于印度的公司。

  • 搜索:在公司列表中搜索公司名的 API 端點(diǎn)應(yīng)當(dāng)是 GET /companies?search=Digital。

  • 分頁(yè):當(dāng)數(shù)據(jù)集太大時(shí),我們應(yīng)當(dāng)將數(shù)據(jù)集分割成小的數(shù)據(jù)塊,這樣有利于提升服務(wù)端性能,也方便客戶(hù)端處理響應(yīng)。如 GET /companies?page=23 意味著獲取公司列表的第 23 頁(yè)數(shù)據(jù)。

2.9. Restful API 版本

??一般使用不帶點(diǎn)的簡(jiǎn)單數(shù)字表示版本,數(shù)字前加字母v代表版本號(hào),如下所示:

  • /blog/api/v1

  • http://api.yourservice.com/v1/companies/34/employees

2.10. 處理 JSON 錯(cuò)誤體

??API 錯(cuò)誤處理機(jī)制是很重要的,而且要好好規(guī)劃。極力推薦總是在返回字段中包含錯(cuò)誤消息。一個(gè) JSON 錯(cuò)誤體應(yīng)當(dāng)為開(kāi)發(fā)者提供一些有用的信息:錯(cuò)誤消息、錯(cuò)誤代碼以及詳細(xì)描述。下面是一個(gè)較好的示例:

{

??? "code": 1234,

??? "message": "Something bad happened :(",

??? "description": "More details about the error here"

}

2.11. 如何創(chuàng)建 Rest API URL

??推薦使用下面格式的 URL:

  • http(s)/{域名(:端口號(hào))}/{表示REST API的值}/{API版本}/{識(shí)別資源的路徑}

  • http(s)/{表示REST API的域名(:端口號(hào))}/{API 版本}/{識(shí)別資源的路徑}

    ??如下所示:

  • http://example.com/api/v1/members/M000000001

  • http://api.example.com/v1/members/M000000001

3. 開(kāi)發(fā)基于 Spring Boot 的 Restful Web 服務(wù)

??Spring Boot 提供了構(gòu)建企業(yè)應(yīng)用中 RESTful Web 服務(wù)的極佳支持。

3.1. 引入依賴(lài)


??要構(gòu)建 RESTful Web 服務(wù),我們需要在構(gòu)建配置文件中加上 Spring Boot Starter Web 依賴(lài)。

??對(duì)于 Maven 用戶(hù),使用以下的代碼在 pom.xml 文件中加入依賴(lài):


<dependency>

?? <groupId>org.springframework.boot</groupId>

?? <artifactId>spring-boot-starter-web</artifactId>???

</dependency>

??對(duì)于 Gradle 用戶(hù),使用以下的代碼在 build.gradle 文件中加入依賴(lài):

compile('org.springframework.boot:spring-boot-starter-web')

3.2. Rest 相關(guān)注解

??在繼續(xù)構(gòu)建 RESTful web 服務(wù)前,建議你先要熟悉下面的注解:

Rest Controller

??@RestController 注解用于定義 RESTful web 服務(wù)。它提供 JSON、XML 和自定義響應(yīng)。語(yǔ)法如下所示:

@RestController

public class ProductServiceController {

}

Request Mapping

??@RequestMapping 注解用于定義請(qǐng)求 URI 以訪(fǎng)問(wèn) REST 端點(diǎn)。我們可以定義 Request 方法來(lái)消費(fèi) produce 對(duì)象。默認(rèn)的請(qǐng)求方法是 GET:

@RequestMapping(value = "/products")

public ResponseEntity<Object> getProducts() { }

Request Body

?? @RequestBody 注解用于定義請(qǐng)求體內(nèi)容類(lèi)型。

public ResponseEntity<Object> createProduct(@RequestBody Product product) {

}

Path Variable

??@PathVariable 注解被用于定義自定義或動(dòng)態(tài)的請(qǐng)求 URI,Path variable 被放在請(qǐng)求 URI 中的大括號(hào)內(nèi),如下所示:

public ResponseEntity<Object> updateProduct(@PathVariable("id") String id) {

}

1.2.

Request Parameter


??@RequestParam 注解被用于從請(qǐng)求 URL 中讀取請(qǐng)求參數(shù)。缺省情況下是必須的,也可以為請(qǐng)求參數(shù)設(shè)置默認(rèn)值。如下所示:

public ResponseEntity<Object> getProduct(

@RequestParam(value = “name”, required = false, defaultValue = “honey”) String name) {

}


3.3. 編寫(xiě) REST API

GET API


??下面的示例代碼定義了 HTTP GET 請(qǐng)求方法。在這個(gè)例子里,我們使用 HashMap 來(lái)在存儲(chǔ) Product。注意我們使用了 POJO 類(lèi)來(lái)存儲(chǔ)產(chǎn)品。

??在這里,請(qǐng)求 URI 是 /products,它會(huì)從 HashMap 倉(cāng)儲(chǔ)中返回產(chǎn)品列表。下面的控制器類(lèi)文件包含了 GET 方法的 REST 端點(diǎn):


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);

?? }

}

POST API


??HTTP POST 請(qǐng)求用于創(chuàng)建資源。這個(gè)方法包含請(qǐng)求體。我們可以通過(guò)發(fā)送請(qǐng)求參數(shù)和路徑變量來(lái)定義自定義或動(dòng)態(tài) URL。

??下面的示例代碼定義了 HTTP POST 請(qǐng)求方法。在這個(gè)例子中,我們使用 HashMap 來(lái)存儲(chǔ) Product,這里產(chǎn)品是一個(gè) POJO 類(lèi)。

??這里,請(qǐng)求 URI 是 /products,在產(chǎn)品被存入 HashMap 倉(cāng)儲(chǔ)后,它會(huì)返回字符串。


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);

?? }

}

PUT API


??HTTP PUT 請(qǐng)求用于更新已有的資源。這個(gè)方法包含請(qǐng)求體。我們可以通過(guò)發(fā)送請(qǐng)求參數(shù)和路徑變量來(lái)定義自定義或動(dòng)態(tài) URL。

??下面的例子展示了如何定義 HTTP PUT 請(qǐng)求方法。在這個(gè)例子中,我們使用 HashMap 更新現(xiàn)存的產(chǎn)品。此處,產(chǎn)品是一個(gè) POJO 類(lèi)。

??這里,請(qǐng)求 URI 是 /products/{id},在產(chǎn)品被存入 HashMap 倉(cāng)儲(chǔ)后,它會(huì)返回字符串。注意我們使用路徑變量 {id} 定義需要更新的產(chǎn)品 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);

?? }??

}

DELETE API


??HTTP Delete 請(qǐng)求用于刪除存在的資源。這個(gè)方法不包含任何請(qǐng)求體。我們可以通過(guò)發(fā)送請(qǐng)求參數(shù)和路徑變量來(lái)定義自定義或動(dòng)態(tài) URL。

??下面的例子展示如何定義 HTTP DELETE 請(qǐng)求方法。這個(gè)例子中,我們使用 HashMap 來(lái)移除現(xiàn)存的產(chǎn)品,用 POJO 來(lái)表示。

??請(qǐng)求 URI 是 /products/{id} 在產(chǎn)品被從 HashMap 倉(cāng)儲(chǔ)中刪除后,它會(huì)返回字符串。 我們使用路徑變量 {id} 來(lái)定義要被刪除的產(chǎn)品 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);

?? }

}


搭建 Restful Web 服務(wù)的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
调兵山市| 溧阳市| 汾西县| 常山县| 铜川市| 吴江市| 老河口市| 兴仁县| 阿克陶县| 鄂托克前旗| 炉霍县| 青铜峡市| 轮台县| 屏东县| 克什克腾旗| 商丘市| 德兴市| 保康县| 宁阳县| 东阿县| 磐安县| 平原县| 如东县| 大田县| 抚松县| 吉木萨尔县| 苗栗县| 邻水| 莱阳市| 玉环县| 宜兰市| 城口县| 桐柏县| 饶阳县| 旬邑县| 内黄县| 辛集市| 汕尾市| 鹿泉市| 济源市| 天峻县|