自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一篇帶你理解Restful風(fēng)格

開(kāi)發(fā) 架構(gòu)
REST本身是一個(gè)比較大的概念,但是在如今前已經(jīng)后端分離、微服務(wù)化等概念逐漸普及,原本的REST概念并非完全的適用。但是REST的核心理念對(duì)我們的接口規(guī)范設(shè)計(jì)有十分重要的指導(dǎo)性意見(jiàn)。

REST是什么

REST從2000年被Roy Fielding提出距今已有20多年,其對(duì)Web技術(shù)產(chǎn)生了深遠(yuǎn)的影響。REST本身并沒(méi)有產(chǎn)生新的技術(shù)或者中間件,REST傳遞的是一種設(shè)計(jì)思想,其提供了一種約束原則和條件。

REST全稱為Representational State Transfer,中文為表征性狀態(tài)轉(zhuǎn)移,感覺(jué)前面其實(shí)還少了一個(gè)主語(yǔ)“資源”,個(gè)人理解應(yīng)該是“資源表征性狀態(tài)轉(zhuǎn)移”。而其核心就是通過(guò)創(chuàng)造一種資源的定義與描述原則,形成一種標(biāo)準(zhǔn)化規(guī)范,從而減少技術(shù)人員在開(kāi)發(fā)與溝通時(shí)候的成本。

實(shí)現(xiàn)REST風(fēng)格的框架叫Restful架構(gòu)時(shí),而我們主要是使用的HTTP作為這種規(guī)范的載體,本文也是針對(duì)HTTP的形式來(lái)進(jìn)行討論。但我認(rèn)為,只要滿足REST設(shè)計(jì)思想的功能描述方式,都可以算作REST的實(shí)現(xiàn),其并不局限于HTTP協(xié)議。

理解REST

Representational State Transfer,其實(shí)已經(jīng)將REST的整體概念羅列出來(lái)了,加上我們補(bǔ)充的主語(yǔ)“資源”,可以很明確的體現(xiàn)出REST中主要的兩個(gè)概念:

  • 資源,資源表征
  • 動(dòng)作,狀態(tài)轉(zhuǎn)移

簡(jiǎn)單理解的話,REST是就是將一個(gè)接口動(dòng)作的描述進(jìn)行拆分,拆分成資源與動(dòng)作兩個(gè)部分。其中,資源就是對(duì)描述資源位置,資源表征則是這些資源應(yīng)該如何展示出來(lái)(具體是JSON還是XML),而狀態(tài)轉(zhuǎn)移則可以簡(jiǎn)單的理解成正對(duì)這個(gè)資源所進(jìn)行的動(dòng)作。

REST的正是通過(guò)將這兩種核心定義的邏輯進(jìn)行分離、標(biāo)準(zhǔn)化,從而讓對(duì)于“接口”、“操作”的定義更加便于理解,和可閱讀(更完成權(quán)威的介紹可以參考:

https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm)。

資源

REST中的核心概念之一是對(duì)資源的的描述,而這個(gè)資源是一個(gè)抽象概念,并不一定是一個(gè)靜態(tài)的資源,也可以是完整資源的一部分。實(shí)際上,只要是可以被引用的部分,我們都可以稱之為一個(gè)資源。

而在web中我們標(biāo)識(shí)一個(gè)資源使用的是URI(Uniform Resource Identifier)。從定義上來(lái)講,URI是唯一標(biāo)識(shí)符,即可以說(shuō)是資源的名稱也可以說(shuō)是資源的地址。從這個(gè)角度上來(lái)說(shuō)如果無(wú)法用URI來(lái)表示一個(gè)內(nèi)容,那么就不能說(shuō)它是一個(gè)資源。

一些正面的例子:

https://blog.csdn.net/losorick/article/details/123311537。

https://xie.infoq.cn/article/3ddce663b21acd89f41582aa3。

一些反面的例子:

/export/create。

資源定義中多個(gè)名詞之間用"-"(最好不用用"_",會(huì)在特定情況下顯示不完全)來(lái)進(jìn)行分割,并用"/"來(lái)表示資源增肌的概念。也可以用","或者";"來(lái)作為多個(gè)資源的分割。當(dāng)然這些都是建議建議,對(duì)于具體的實(shí)施只要項(xiàng)目中統(tǒng)一就行,比如github中就是使用"..."來(lái)作為多個(gè)資源的分割,例如“/git/git/compare/master…next”。

資源表征

URI只定位了具體的資源,但對(duì)于客戶端來(lái)說(shuō)是這是一個(gè)統(tǒng)一的抽象。如果客戶端要使用的話并不能直接使用,需要指明所需要使用的資源形式。當(dāng)前主流的文本交互方式表征是JSON格式,當(dāng)然對(duì)于要求響應(yīng)格式嚴(yán)謹(jǐn)?shù)膱F(tuán)隊(duì)來(lái)說(shuō)仍然有使用XML格式的,而對(duì)于媒體資源來(lái)說(shuō)也有PNG、MP4等形式。

原則上,資源定位符只負(fù)責(zé)資源的標(biāo)識(shí),但是并不關(guān)注具體怎么展示資源,而需要用何種形式展示資源則是由客戶端根據(jù)自己的需要申請(qǐng)的。在HTTP中我們服務(wù)端通常使用“content-type”來(lái)對(duì)資源的表征來(lái)進(jìn)行描述,而客戶端則是用“Accept”請(qǐng)求頭中來(lái)指明所需要的格式類型。

同時(shí),資源的表征并不局限在資源的輸出類型上,資源間的關(guān)聯(lián)關(guān)系也是資源表征的一部分。舉例而言,當(dāng)我們查詢一個(gè)詳情信息,查詢后的響應(yīng)體本身是一個(gè)資源,用于描述這個(gè)詳情信息。如果需求要我們描述這個(gè)詳情信息后的下一個(gè)詳情信息的訪問(wèn)鏈接,用于提示用戶進(jìn)一步瀏覽。這個(gè)信息“下一個(gè)鏈接”的信息,如果我們放到響應(yīng)體中似乎并不是很合適,因?yàn)檫@對(duì)于一個(gè)GET請(qǐng)求來(lái)說(shuō),這個(gè)“下一個(gè)鏈接”信息并不是資源本身的一部分。并且隨著系統(tǒng)中推薦算法的運(yùn)行,這部分信息甚至變成不可緩存的內(nèi)容(因?yàn)榭赡茈S時(shí)發(fā)生改變)?;谝陨嫌懻?,或許我們?cè)黾右粋€(gè)LINK響應(yīng)頭用來(lái)描述“下一個(gè)鏈接”的信息,就達(dá)到了目的并保證了響應(yīng)體對(duì)于資源本身描述的正確性。

所以,資源表征并非是對(duì)數(shù)據(jù)庫(kù)的CURD,它體現(xiàn)了資源作為一個(gè)超媒體中一部分的這個(gè)概念(資源與資源的連接關(guān)系)。同時(shí)我們可以使用HTTP中的各個(gè)部分來(lái)獨(dú)立的描述各種概念,而非一股腦的都丟到響應(yīng)體中。

狀態(tài)轉(zhuǎn)移

通過(guò)上文中的描述,我們可以將資源理解成了一種靜態(tài)的內(nèi)容。那么該如何理解我們對(duì)資源的操作呢?REST是用狀態(tài)轉(zhuǎn)移來(lái)表述這件事的。當(dāng)我們新建一個(gè)資源時(shí),就將資源從“無(wú)”狀態(tài)轉(zhuǎn)移為了存在狀態(tài);當(dāng)我們更新一個(gè)資源的時(shí),則是讓其內(nèi)部的狀態(tài)發(fā)生了更改。

REST中的是使用HTTP方法來(lái)描述這些操作類型的,這樣的好處是,我們可以為操作類型指定統(tǒng)一的規(guī)范。舉個(gè)例子來(lái)說(shuō),在REST中所有的GET請(qǐng)求都應(yīng)該是可以被緩存的,所有的PUT請(qǐng)求都應(yīng)該是冪等的。我們通過(guò)將接口操作約束成明確的HTTP方法或者是其他統(tǒng)一方式,從而減少在接口對(duì)接查看時(shí)的溝通成本。

常用的HTTP方法主要是:GET、POST、PUT、DELETE。但是更早版本的客戶端可能只有GET和POST。而根據(jù)協(xié)議的升級(jí)則支持LOCK、UNLOCK等方法以及自定義方法。但通常企業(yè)內(nèi)會(huì)根據(jù)自己的主要受眾設(shè)備進(jìn)行調(diào)整這些設(shè)計(jì)。

從Restful出發(fā)的接口規(guī)范

對(duì)于一個(gè)接口,其中的URI部分應(yīng)該只用于描述操作時(shí)針對(duì)哪個(gè)資源的。而“HTTP方法”應(yīng)該才用于解釋操作的類型的。但是企業(yè)中如果要推行REST接口的規(guī)范的話,仍然有一些問(wèn)題需要調(diào)整確認(rèn),原因可能是內(nèi)部歷史原因或者當(dāng)前框架與REST并不適配,本小節(jié)舉例其中的兩個(gè)例子用于各位參考。

向下兼容

由于在業(yè)務(wù)實(shí)際開(kāi)發(fā)的過(guò)程中,可能會(huì)出現(xiàn)業(yè)務(wù)的邏輯變更,我們處理這種問(wèn)題的主要方法就是通過(guò)對(duì)接口添加版本信息來(lái)實(shí)現(xiàn)的。

但是由上文可知,URI本身應(yīng)該用于定義資源的名稱和地址。所以對(duì)于同一個(gè)資源來(lái)說(shuō),內(nèi)容變了就是變了,資源本身是沒(méi)有版本的概念,我們實(shí)際上調(diào)整的是資源的不同的表征方式,而這個(gè)方式才對(duì)應(yīng)的“版本”的概念,而非資源本身。如果是從這個(gè)角度出發(fā),對(duì)于REST的設(shè)計(jì)來(lái)說(shuō),這個(gè)版本的概念就不應(yīng)該出現(xiàn)在URI的資源定位符上,因?yàn)橘Y源的名稱都是同一個(gè)。那么對(duì)于REST我們可以通過(guò)在Accept響應(yīng)頭追加版本信息(version)來(lái)區(qū)分具體的表征方式。例如:

  • Accept: version=1.0。
  • Accept: version=2.1。
  • Accept: version=3.0。

但是在實(shí)際的企業(yè)中,我們通常不會(huì)這么做。原因有很多,其中一種是因?yàn)樵跇I(yè)務(wù)溝通的時(shí)候,通常只聚焦在URI和HTTP方法上。在實(shí)際溝通中我們將URI和HTTP方法作為互相溝通的主要方法,并可以通過(guò)一行就表示出全部信息,例如:

  • {GET} http://api.example.com/trade/order/1。

所以如果在URI地址上直接添加版本信息,就可以通過(guò)以下方式表示:

  • {GET} http://api.example.com/trade/v1/order/1。
  • {GET} http://api.example.com/trade/v2/order/1。
  • {GET} http://api.example.com/trade/v3/order/1。

這樣的好處就是可以通過(guò)URI直接描述兼容性信息,而缺點(diǎn)就是破壞了REST原教旨主義的資源定位方法。但REST推出到當(dāng)前已有20多年時(shí)間,而實(shí)際業(yè)務(wù)中“資源”數(shù)量也已經(jīng)爆炸數(shù)量增長(zhǎng)。所以在服務(wù)治理等各種新概念成為必要需求的今天,符合現(xiàn)狀的調(diào)整才是合適的。

定制的操作

在REST中我們需要用HTTP的方法來(lái)定義操作的類型,那么就有一個(gè)主要問(wèn)題:已有方法無(wú)法描述當(dāng)前操作怎么辦。一些常見(jiàn)的操作(Postman中有的)是PATCH(github有)、COPY、LINK等。除此之外常見(jiàn)的還有BATCH- CREATE等批量操作。

如果根據(jù)REST原教旨主義則應(yīng)該在HTTP方法中進(jìn)行擴(kuò)展,但由于系統(tǒng)兼容性等問(wèn)題,我們希望保證各種版本的客戶端可以對(duì)方法進(jìn)行支持。

首先,不論我們是使用什么方法來(lái)表示自定義操作,都需要滿足統(tǒng)一表達(dá),并且可以應(yīng)用在所有的方法中。根據(jù)這種情況,本小結(jié)列舉出幾種方案作為參考:

擴(kuò)展方法

HTTP中的方法可以自己擴(kuò)展,Github新增了PATCH方法,WebDAV中擴(kuò)展了LOCK、UPLOCK等方法,但這些都不是HTTP中的標(biāo)準(zhǔn)方法,如果使用該方法需要考慮客戶端的支持能力。

參數(shù)定義

通過(guò)使用預(yù)留參數(shù)定義擴(kuò)展方法,例如使用_method=DELETE來(lái)對(duì)請(qǐng)求方法來(lái)定義,并在服務(wù)端對(duì)具體方法進(jìn)行路由。這種方法的好處是可以將參數(shù)代入到URI中,并不影響URI原版本的資源定位的意義。

URI后綴描述

可以通過(guò)在URI添加后綴來(lái)描述動(dòng)作,例如在后綴添加/actions:delete來(lái)定義,或者在URI最后使用/actions標(biāo)記,并在請(qǐng)求體中第一層來(lái)描述擴(kuò)展的動(dòng)作類型。這樣雖然導(dǎo)致URI定義中加入了額外的資源地址之外的額外信息,但是可以保證整體訪問(wèn)接口中的信息是完整的。

總體來(lái)說(shuō),對(duì)于確定定制操作的擴(kuò)展方案要在客戶端支持成都、下游網(wǎng)關(guān)改造難度以及接口可讀性中做出平衡。

Restful風(fēng)格的問(wèn)題

使用Restful風(fēng)格的構(gòu)建項(xiàng)目中主要需要的問(wèn)題就是關(guān)于path-variable的處理問(wèn)題。在一些項(xiàng)目治理項(xiàng)目中默認(rèn)是認(rèn)為有path-variable引起的不同path是不同的URL,所以無(wú)法直接使用,需要具有開(kāi)源軟件二次開(kāi)發(fā)的能力和需求。

舉一個(gè)Sentinel的例子,Sentinel是根據(jù)url生成的資源名稱,而因?yàn)镽EST中用path-variable來(lái)定義資源,所以就導(dǎo)致了同一類資源的定義符被識(shí)別成了不同的資源。

但隨著查看Sentinel中的代碼我們可以發(fā)現(xiàn),Sentinel中默認(rèn)使用CommonFilter來(lái)處理請(qǐng)求的url,并且主要是通過(guò)UrlCleaner接口中的clean方法來(lái)對(duì)資源進(jìn)行重命名,所以我們可以通過(guò)重寫(xiě)clean方法實(shí)現(xiàn)滿足rest的資源明明問(wèn)題(事實(shí)上官方也提供了

sentinel-spring-webmvc-adapter來(lái)支持rest風(fēng)格定義的接口)。

由于REST風(fēng)格是主流的接口規(guī)范風(fēng)格之一,所以使用量較大的中間件一會(huì)都會(huì)有對(duì)應(yīng)的解決方案,但是對(duì)于自研的工具需要考慮REST風(fēng)格的兼容性,可以參考一些開(kāi)源軟件如Swagger的匹配來(lái)實(shí)現(xiàn)。

最后

本文討論了REST中的相關(guān)概念,并非完全照本宣科的進(jìn)行陳述,如REST的6大指導(dǎo)原則也并沒(méi)有介紹。REST本身是一個(gè)比較大的概念,但是在如今前已經(jīng)后端分離、微服務(wù)化等概念逐漸普及,原本的REST概念并非完全的適用。但是REST的核心理念對(duì)我們的接口規(guī)范設(shè)計(jì)有十分重要的指導(dǎo)性意見(jiàn)。

責(zé)任編輯:姜華 來(lái)源: 今日頭條
相關(guān)推薦

2020-11-27 08:02:41

Promise

2022-12-20 08:22:42

CommitMuation

2021-05-20 06:57:16

RabbitMQ開(kāi)源消息

2023-04-20 08:00:00

ES搜索引擎MySQL

2021-06-16 08:28:25

unary 方法函數(shù)技術(shù)

2025-01-17 07:00:00

2022-02-24 07:56:42

開(kāi)發(fā)Viteesbuild

2021-05-12 06:18:19

KubeBuilderOperatork8s

2021-05-17 05:51:31

KubeBuilderOperator測(cè)試

2021-05-18 05:40:27

kubebuilderwebhook進(jìn)階

2020-12-29 05:35:43

FlinkSQL排序

2022-02-21 09:44:45

Git開(kāi)源分布式

2023-05-12 08:19:12

Netty程序框架

2021-06-30 00:20:12

Hangfire.NET平臺(tái)

2021-07-28 10:02:54

建造者模式代碼

2021-07-14 08:24:23

TCPIP 通信協(xié)議

2021-05-16 10:52:58

kubebuilderstatus event

2022-04-08 08:32:40

mobx狀態(tài)管理庫(kù)redux

2021-08-11 07:02:21

npm包管理器工具

2021-11-16 14:09:58

Containerd Dockerk8s
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)