者:人月神話,新浪博客同名
簡介:多年SOA規(guī)劃建設(shè),私有云PaaS平臺架構(gòu)設(shè)計經(jīng)驗,長期從事一線項目實踐
在前面關(guān)于微服務(wù)方面的文章里面提到,對于多個微服務(wù)模塊間往往都是以輕量的Http Rest API接口方式進行集成和協(xié)同。那么對于API接口的設(shè)計,接口服務(wù)的注冊接入,后續(xù)的治理管控就是整個微服務(wù)架構(gòu)里面不可或缺的內(nèi)容。因此今天將對這部分內(nèi)容重新做下總結(jié)。
對于HTTP Rest接口的設(shè)計,網(wǎng)上已經(jīng)有很多文章都有詳細的闡述,今天再重新整理下這里面的一些重點,大家都清楚Rest接口是面向資源的接口設(shè)計方法,而且基于原生的Http協(xié)議,因此里面就有兩個最關(guān)鍵的點,一個就是對資源的理解,一個就是對操作的理解。
圖片來源網(wǎng)絡(luò)
什么是RESTful架構(gòu),重要的幾點如下:
對資源的理解
就是我們平常上網(wǎng)訪問的一張圖片、一個文檔、一個視頻等。這些資源我們通過URI來定位,也就是一個URI表示一個資源。資源是做一個具體的實體信息,它可以有多種的展現(xiàn)方式。而把實體展現(xiàn)出來就是表現(xiàn)層,例如一個txt文本信息,它可以輸出成html、json、xml等格式,一個圖片他可以jpg、png等方式展現(xiàn),這個就是表現(xiàn)層的意思。
URI確定一個資源,但是如何確定它的具體表現(xiàn)形式呢?應(yīng)該在HTTP請求的頭信息中用Accept和Content-Type字段指定,這兩個字段才是對”表現(xiàn)層”的描述。
對操作的理解
客戶端能通知服務(wù)器端的手段,只能是HTTP協(xié)議。
具體來說,就是HTTP協(xié)議里面,四個表示操作方式的動詞:GET、POST、PUT、DELETE。它們分別對應(yīng)四種基本操作:GET用來獲取資源,POST用來新建資源(也可以用于更新資源),PUT用來更新資源,DELETE用來刪除資源。
對于資源的任何操作,都應(yīng)該映射到HTTP的幾個有限的方法(常用的有GET/POST/PUT/DELETE 四個方法,還有不常用的PATCH/HEAD/OPTIONS方法)上面。所以RESTful API建模的過程,可以看作是具有統(tǒng)一接口約束的面向?qū)ο蠼_^程。
按照HTTP協(xié)議的規(guī)定,GET方法是安全且冪等的,POST方法是既不安全也不冪等的(可以用來作為所有寫操作的通配方法),PUT、 DELETE方法都是不安全但冪等的。將對資源的操作合理映射到這四個方法上面,既不過度使用某個方法(例如過度使用GET方法或POST方法),也不添 加過多的操作以至于HTTP的四個方法不夠用。
面向資源的設(shè)計
圖片來源網(wǎng)絡(luò)
注意傳統(tǒng)的接口設(shè)計一般是面向方法和操作的,即一般都是動賓結(jié)構(gòu)為主的方法操作。比如查詢用戶信息接口,更新供應(yīng)商狀態(tài)接口,刪除人員信息接口等等。而對于面向資源的設(shè)計,一個大的轉(zhuǎn)變就是首先要識別和定義資源,再來對資源的Http各種操作方法進行定義。
資源可以理解為對象,更多的是數(shù)據(jù)模型,這種數(shù)據(jù)模型本身就是有層次結(jié)構(gòu),本身是可以嵌套或遞進的。比如你可以將訂單理解為一個資源,那么這個訂單資源本身是一個層次化的結(jié)構(gòu)對象,包括了訂單頭信息,也包括了訂單明細信息。我們可以對這個層次化的資源結(jié)構(gòu)進行詳細定義。
在數(shù)據(jù)庫設(shè)計的時候,經(jīng)常會出現(xiàn)視圖的設(shè)計,或者說表之間的關(guān)聯(lián),而這種視圖本身就不是一種資源實體,但是在進行資源定義的時候,我們可以定義這種層次化的對象結(jié)構(gòu)。
舉個例子來說,在對訂單這種資源對象進行定義的時候,在訂單明細中傳統(tǒng)的視圖中會關(guān)聯(lián)訂單明細表和物料表形成訂單行ID,物料編碼ID,物料名稱,類型,訂購數(shù)量的關(guān)聯(lián)視圖信息。但是在資源定義的時候,我們?nèi)匀恢恍枰x訂單行信息,但是訂單行信息中出現(xiàn)了物料,我們形成一個對物料資源信息的Ref引用,而獲取到完整的物料屬性信息。
當(dāng)然資源本身也有關(guān)聯(lián)關(guān)系,我們可以定義這種關(guān)聯(lián)關(guān)系來獲取到關(guān)聯(lián)資源的信息,比如某個用戶發(fā)布的評論信息,我們可以先定位到該用戶資源,然后再定位到該用戶資源對應(yīng)的評論資源。
具體可以參考:
http://www.ruanyifeng.com/blog/2014/05/restful_api.html
http://blog.51cto.com/xxdeelon/2083707
為了使 API 看上去簡單明了,可讀性強,我們一般使用名詞,而不是動詞來命名這些資源。比如下面這些都是糟糕的設(shè)計,比如下面的動賓結(jié)構(gòu)的方法名作為資源:
之所以糟糕,不僅僅是它們顯得拖沓冗長,最重要的是,使用這樣的風(fēng)格和名字沒有固定的形式,不同的開發(fā)者往往需要閱讀你的文檔才能開始使用,也沒有充分利用HTTP Method,何況使用自己的動詞可能會產(chǎn)生和HTTP Method沖突的情況。使用 REST 風(fēng)格的優(yōu)秀設(shè)計應(yīng)該像下面這些:
這些API所有的操作只有一個節(jié)點 /users,顯得簡潔明了,如果熟悉 HTTP Method 的開發(fā)者,一眼看上去就能猜到應(yīng)該如何使用。
注:在現(xiàn)在進行Http Rest API接口設(shè)計的時候,實際上往往并沒有遵循面向資源設(shè)計的思路,仍然是參考上面的操作+數(shù)據(jù)的設(shè)計方法,比如有些公司的設(shè)計規(guī)范往往還是全部約定為使用POST接口設(shè)計,這個并不能說就一定不合理。這種情況更多就是使用Http API而已。
您可能已經(jīng)注意到了,以上 API 中資源命名都使用了復(fù)數(shù)的形式。這是一個約定,它可以省去設(shè)計時考慮數(shù)據(jù)具體細節(jié)的麻煩(數(shù)據(jù)是復(fù)數(shù)還是單數(shù)?)。現(xiàn)在大很多常見的系統(tǒng)都使用了復(fù)數(shù)形式。比如Twitter 的 REST APIs 和 Facebook 的 Graph API 基本都是復(fù)數(shù)形式。
然而實際系統(tǒng)一般都不可能只有單一資源,資源和資源之間有各種關(guān)系是很正常的情況,那么如何設(shè)計存在關(guān)聯(lián)資源(數(shù)據(jù))的API呢?如果要設(shè)計一個資源擁有另外一個資源的情況的API,例如,設(shè)計一個包含用戶(users)和用戶的評論(comments)的 API 可以采用這樣的形式:
當(dāng)然,如果一個資源并不依附其它資源而可以獨立存在,是沒有必要這樣設(shè)計的,完全可以使用和 users 一樣的形式提供,如果要查詢其中的關(guān)系,可以使用其它資源作為 ID 的形式來過濾。
例如 /comments?user_id=1234。關(guān)于這點詳細內(nèi)容可以參見下面的第三條“優(yōu)雅的設(shè)計條件過濾,排序,搜索和限制返回數(shù)據(jù)的參數(shù)形式”。
對于Http Rest接口設(shè)計規(guī)范,可參考
https://blog.csdn.net/zghwaicsdn/article/details/53788535
https://blog.csdn.net/zl1zl2zl3/article/details/73867113
https://blog.csdn.net/yyjava/article/details/81626991
https://www.jianshu.com/p/00d1ab8cc073
http://wangwei.info/about-rest-api/
資源定義格式:
URI=scheme "://" authority "/" path [ "?" query ] [ "#" fragment ]
URL是URI的一個子集(一種具體實現(xiàn)),對于REST API來說一個資源一般對應(yīng)一個唯一的URI(URL)。在URI的設(shè)計中,我們會遵循一些規(guī)則,使接口看起透明易讀,方便使用者調(diào)用。
"/"分隔符一般用來對資源層級的劃分
例如 http://api.canvas.restapi.org/shapes/polygons/quadrilaterals/squares
對于REST API來說,"/"只是一個分隔符,并無其他含義。為了避免混淆,"/"不應(yīng)該出現(xiàn)在URL的末尾。
在RESTful架構(gòu)中,每個網(wǎng)址代表一種資源(resource),所以網(wǎng)址中不能有動詞,只能有名詞,而且所用的名詞往往與數(shù)據(jù)庫的表格名對應(yīng)。一般來說,數(shù)據(jù)庫中的表都是同種記錄的"集合"(collection),所以API中的名詞也應(yīng)該使用復(fù)數(shù)。
在我們在實施過程中如何通過一些工具支撐來進行接口設(shè)計的規(guī)范化和標(biāo)準(zhǔn)化問題。大家都知道,在采用傳統(tǒng)的SOAP WebService服務(wù)接口的時候,由于SOAP WS服務(wù)本身有WSDL和XSD文件的強接口契約規(guī)范格式要求,因此很容易基于從上向下,規(guī)范先行的思路來進行服務(wù)實施流程管控。即:
可以看到傳統(tǒng)的WS服務(wù)實施下,我們可以通過規(guī)范和契約先行的方式很好的控制接口的標(biāo)準(zhǔn)化和一致性,同時大家遵循完全相同的一套WSDL文件進行接口的提供或開發(fā),基本不存在接口實現(xiàn)中數(shù)據(jù)結(jié)構(gòu)不一致的問題。
在采用RestAPI接口進行設(shè)計的時候,實際上仍然有一個關(guān)鍵點,就是設(shè)計要先行,先設(shè)計,然后再進行開發(fā)和測試,同時設(shè)計文件能給標(biāo)準(zhǔn)化和結(jié)構(gòu)化,通過設(shè)計文件來生成相應(yīng)的客戶端和服務(wù)端代碼框架,通過設(shè)計文件來生成相應(yīng)的測試用例,通過設(shè)計文件來生成對應(yīng)的API接口設(shè)計文檔。
設(shè)計先行,是Http Rest接口服務(wù)實施中的一個關(guān)鍵點。
1. 設(shè)計工具的選擇問題
當(dāng)前兩者主流的設(shè)計規(guī)范和建模語言,一個是RAML,一個是WADL。
RAML(RESTful API Modeling Language) 即 RESTful API 建模語言)是對 RESTful API的一種簡單和直接的描述。它是一種讓人們易于閱讀并且能讓機器對特定的文檔能解析的語言。
RAML 是基于 YAML,能幫助設(shè)計 RESTful API 和鼓勵對API的發(fā)掘和重用,依靠標(biāo)準(zhǔn)和最佳實踐從而編寫更高質(zhì)量的API。通過RAML定義,因為機器能夠看得懂,所以可以衍生出一些附加的功能服務(wù),像是解析并自動生成對應(yīng)的客戶端調(diào)用代碼、服務(wù)端代碼 結(jié)構(gòu), API說明文檔。
https://www.w3cschool.cn/web_api_next/qw2zpozt.html
https://raml.org/projects
https://www.cnblogs.com/softidea/p/5728952.html
WADL(Web Application Description Language)是一種用于描述web應(yīng)用對外提供接口語言,它使用XML來表示。其中主要包括每個資源的定位(URI)、請求類型(GET、POST等)、請求參數(shù)類型(路徑參數(shù)、query參數(shù)等)、響應(yīng)值和響應(yīng)類型等一系列內(nèi)容。
根據(jù)這個XML,可以直接讀取到系統(tǒng)提供的所有REST API,并能夠進行調(diào)用。由于WADL使用XML描述,對于開發(fā)者來說,可以通過標(biāo)準(zhǔn)的xslt進行轉(zhuǎn)換,將機器讀取的XML轉(zhuǎn)換成便于人讀取的HTML,進而行成API文檔。
https://coolex.info/blog/547.html
http://blog.chinaunix.net/uid-9789791-id-1997442.html
http://www.doc88.com/p-6661149184381.html
注:對于兩種接口規(guī)范如何選擇的問題?個人認(rèn)為如果我們需要一套接口規(guī)范同時兼容傳統(tǒng)的SAOP WebService和Http Rest API,那么采用WADL更好。如果已經(jīng)是全新Http Rest接口設(shè)計,往往當(dāng)前RAML更加主流。
主流的Swagger設(shè)計工具
對于設(shè)計工具,這里只談下Swagger設(shè)計工具,這個工具最大的好處就是只需要通過編輯器進行Rest接口設(shè)計文件的定義,然后可以自動生成測試框架,自動生成客戶端和服務(wù)端多種語言下的開發(fā)框架,生成API接口設(shè)計文檔,這個工具本身設(shè)計完成內(nèi)容還可以導(dǎo)出為YAML文件或Json文件,也支撐文件導(dǎo)入。
https://swagger.io/tools/
Swagger 是一個規(guī)范和完整的框架,用于生成、描述、調(diào)用和可視化 RESTful 風(fēng)格的 Web 服務(wù)。Swagger的目標(biāo)是對REST API定義一個標(biāo)準(zhǔn)的和語言無關(guān)的接口,可讓人和計算機無需訪問源碼、文檔或網(wǎng)絡(luò)流量監(jiān)測就可以發(fā)現(xiàn)和理解服務(wù)的能力。
當(dāng)通過Swagger進行正確定義,用戶可以理解遠程服務(wù)并使用最少實現(xiàn)邏輯與遠程服務(wù)進行交互。與為底層編程所實現(xiàn)的接口類似,Swagger消除了調(diào)用服務(wù)時可能會有的猜測。Swagger是一組開源項目,其中主要要項目如下:
Swagger API Spec包含以下部分內(nèi)容,詳細參考:
https://www.cnblogs.com/jpfss/p/8072443.html
注意通過Swagger-Editor編輯器可以完成整個接口的定義和接口設(shè)計工作,同時一方面用于客戶端和服務(wù)端代碼框架的生成,一方面用于幫助文檔的生成。但是Swagger對于幫助文檔的生成需要在代碼框架里面增加注解,相對來說注解編寫的工作量較大。這也是網(wǎng)上很多提到的文檔生成方面Swagger往往并不是最佳選擇。
原有的接口服務(wù)規(guī)范編寫思路改進
對于原來的接口服務(wù)規(guī)范編寫思路,可以看到幾個改進或優(yōu)化思路。
1. 還是保留先編寫Word格式的接口服務(wù)規(guī)范,然后再將Word接口服務(wù)規(guī)范轉(zhuǎn)為標(biāo)準(zhǔn)的YAML或WADL接口規(guī)范定義文件,同時再生產(chǎn)客戶端或服務(wù)端的代碼框架文件。
2. 拋棄Word編寫規(guī)范模式,直接在類似Swagger編輯器中對接口文件進行設(shè)計,設(shè)計完成后發(fā)出文件進行評審和檢查,沒問題后由集成平臺歸檔并導(dǎo)入管控生產(chǎn)服務(wù)規(guī)范,同時生成客戶端和服務(wù)端代碼框架一同下發(fā)。
現(xiàn)在發(fā)現(xiàn)的一個問題不好解決點在于,在進行接口文件設(shè)計的時候能否直接增加字段和數(shù)據(jù)項的中文描述和業(yè)務(wù)備注說明,該信息最終體現(xiàn)到生成的文檔上。或者說我們需要通過YAML或Json文件,來逆向生成Word文檔,然后Word文檔再下發(fā)給業(yè)務(wù)系統(tǒng)補充中文描述信息。
API文檔的生成
如果采用Swagger工具來進行API接口服務(wù)的設(shè)計,可以看到在編輯器里面,設(shè)計過程和文檔生成過程基本是同步的,即一個API接口設(shè)計好后,文檔基本就已經(jīng)生成完成并可用。當(dāng)前唯一發(fā)現(xiàn)的問題就是沒有想過的中文描述,如果需要中文信息,還需要在代碼框架里面增加注解,這個過程來說就想到繁瑣了。
通過Swagger注解生成文檔:
https://www.jianshu.com/p/0438034ee55f
SpringBoot項目生成RESTfull API的文檔,第二篇給出SpringBoot和Swagger整合思路
https://www.jianshu.com/p/af7a6f29bf4f
http://blog.didispace.com/springbootswagger2/
https://gitee.com/didispace/SpringBoot-Learning
Wisdom REST Client
Wisdom RESTClient supports automated testing and automatically generating RESTful API document based on history cases. Wisdom RESTClient可以自動化測試RESTful API 接口,同時,基于測試過的歷史數(shù)據(jù),可以自動生成API文檔。
工具地址:https://github.com/Wisdom-Projects/rest-client
這個工具是偏測試后的文檔生成,最終生成的文檔展現(xiàn)和Swagger展現(xiàn)效果類似。
Api2Doc文檔生成工具
Api2Doc 專注于 Restful API 文檔的自動生成,它的原理與 Swagger2 是類似的,都是通過反射,分析 Controller 中的信息生成文檔,但它要比 Swagger2 好很多。最大的不同是: Api2Doc 比 Swagger2 要少寫很多代碼。
第一是對應(yīng)注解過程本身更加簡單,其次就是可以自動分析類引用,將類定義中關(guān)于數(shù)據(jù)項的注釋信息引用到最終生成的文檔中,這個功能就相當(dāng)好用了,很好的解決了我們前面提到的數(shù)據(jù)項中文描述的問題。
參考:
http://blog.51cto.com/13613194/2090764
https://www.cnblogs.com/yoyotl/p/6376624.html
使用Asciidoc代替Markdown和Word撰寫開發(fā)文檔
Asciidoc是另外一個可以用于HttpRest接口文檔生成的工具。該工具簡潔而不簡陋的語法,它專門為編寫書籍而生,在語法的支持上很到位,但不像Word那樣可以隨性,可以讓你的文檔更統(tǒng)一美觀。AsciidocFX工具開源跨平臺,使用體驗很不錯,更可以導(dǎo)出HTML、PDF、EBook等格式
具體參考:
https://my.oschina.net/gudaoxuri/blog/524132
http://houqp.github.io/wbwa/wbwa.html
感覺該工具完全可以用于幫助手冊的制作。常用的列表,段落,超鏈接,圖片,表格,代碼等能力都支持。
對于API管理平臺參考
https://www.eolinker.com/#/
對于Eolinker基本提供了一套完整的API全生命周期管理方案。無論您使用什么語言開發(fā),無論是 HTTPS、Websocket、TCP、UDP 等協(xié)議,還是 Restful、SOAP、WebService 等規(guī)范,Eolinker 都可以幫您統(tǒng)一規(guī)范地管理起來,并提供強大的文檔管理、協(xié)作、測試、分享功能。
由于我們原來重點是實施傳統(tǒng)ESB服務(wù)總線項目,以SOAP WS服務(wù)接入為主,并形成了完整的SOA治理管控平臺,實現(xiàn)服務(wù)全生命周期管理和運維監(jiān)控。而對于Http Rest接口服務(wù)的注冊接入和后續(xù)管控,要完全重新實現(xiàn)一套面向Http Rest接口的平臺并不太現(xiàn)實。
因此需要基于當(dāng)前的SOA管控平臺來思考如何平滑擴展對Http Rest接口服務(wù)的支撐能力。
首先我們要意識到,ESB總線和微服務(wù)網(wǎng)關(guān)是可以并行存在的。在一個集團企業(yè)內(nèi)部,有些業(yè)務(wù)域已經(jīng)完全實施微服務(wù)架構(gòu)轉(zhuǎn)型和改造,而有些業(yè)務(wù)系統(tǒng)仍然采用了傳統(tǒng)架構(gòu),企業(yè)在朝微服務(wù)架構(gòu)轉(zhuǎn)型過程中實際上是一個逐漸過渡的過程。在傳統(tǒng)架構(gòu)支撐中我們搭建了ESB企業(yè)服務(wù)總線實現(xiàn)接口服務(wù)集成和統(tǒng)一管控,而在微服務(wù)架構(gòu)支撐中,我們?nèi)绾沃С郑?/p>
這里的一個關(guān)鍵思路和邊界就是,對于某個業(yè)務(wù)域完全實施了微服務(wù)架構(gòu)轉(zhuǎn)型,比如一個大供應(yīng)鏈系統(tǒng)的建設(shè),里面涉及到招投標(biāo),采購,物流,庫存等多個微服務(wù)模塊,都按照微服務(wù)架構(gòu)進行設(shè)計,開發(fā)和集成。那么在這個業(yè)務(wù)域內(nèi)部就需要有微服務(wù)注冊中心,同時又一個微服務(wù)網(wǎng)關(guān)統(tǒng)一提供對外能力。
那么企業(yè)原來已有的全局ESB服務(wù)總線只是和該業(yè)務(wù)域提供的微服務(wù)網(wǎng)關(guān)進行對接。這個有點類似于兩級ESB集成模式,即供應(yīng)鏈內(nèi)部微服務(wù)模塊間的集成不走ESB總線,在內(nèi)部通過注冊中心或網(wǎng)關(guān)完成即可。
其次ESB總線雖然比較重但是不代表性能弱,我們經(jīng)常會遇到業(yè)務(wù)系統(tǒng)提出的問題,就是走ESB服務(wù)總線集成是否太重,而應(yīng)該改為輕量的API網(wǎng)關(guān)類產(chǎn)品。在這里我們要提出一個關(guān)鍵點,就是ESB總線雖然說是一個重型的產(chǎn)品,但是這種重更多是指的其對底層資源和中間件的要求比較高,并不是說重量級的產(chǎn)品性能就差。
對于ESB這種重型產(chǎn)品,底層引擎更加強大,當(dāng)你只啟用簡單的Http服務(wù)代理,安全等功能的時候,其性能,可靠性和穩(wěn)定性反而是遠遠高于我們經(jīng)常說的各種開源的API網(wǎng)關(guān)類產(chǎn)品的。
舉個例子來說,就拿各種重量級的V6大型越野車來說,其重點是油耗高,剛開始的加速弱點,當(dāng)時真正加速起來后的性能,通過性和穩(wěn)定性遠超各種一般的轎車。而且越野車不是說只跑山路爛路有優(yōu)勢,就是其跑高速路帶來的性能你也不上。
微服務(wù)網(wǎng)關(guān)或API網(wǎng)關(guān),我們看到,只要是這種網(wǎng)關(guān)類產(chǎn)品,就一定需要提供服務(wù)代理能力來保證服務(wù)位置透明,但是一提供這個能力,那么所有的消息流就一定會通過網(wǎng)關(guān)來承載,因此API網(wǎng)關(guān)本身受到的性能壓力,高可用性壓力是很大的。也對產(chǎn)品本身也有更高的要求,而對于大型ESB總線在這塊往往已經(jīng)得到充分驗證。
也就是說,要追求性能,我們不要用ESB總線里面類似協(xié)議轉(zhuǎn)換,數(shù)據(jù)映射,適配等復(fù)雜消耗性能的功能,而將ESB總線當(dāng)作網(wǎng)關(guān)類產(chǎn)品來用就可以了,這樣ESB總線完全可以提供類似API網(wǎng)關(guān)應(yīng)該有的性能。
最后,實現(xiàn)對Http Rest接口服務(wù)的注冊和接入并不一定說要完全遵循面向資源編程的思路。談Http Rest接口設(shè)計的時候,一定會提到面向資源的編程思路,包括資源的識別和定義,基于資源的各種標(biāo)準(zhǔn)Http操作。但是要注意到,在一個微服務(wù)架構(gòu)內(nèi)部,我們完全可以按這個思路來執(zhí)行和推廣。但是在涉及到跨域的基礎(chǔ),微服務(wù)網(wǎng)關(guān)和傳統(tǒng)業(yè)務(wù)系統(tǒng),ESB集成的時候。
這個接口設(shè)計是否一定遵循Http Rest面向資源的設(shè)計規(guī)范并不那么重要。
也就是說,傳統(tǒng)ESB在接入Http Rest接口的時候,我們完全可以按傳統(tǒng)的接口設(shè)計方法進行設(shè)計,比如全部走POST接口設(shè)計。只是傳統(tǒng)協(xié)議走了標(biāo)準(zhǔn)的Http接口協(xié)議,傳輸內(nèi)容走了更加輕量的Json格式而已。只有把這點想明白,才能給繼續(xù)思考我們當(dāng)前的SOA管控平臺,如何能給平滑的實現(xiàn)對Http Rest接口服務(wù)接入的支撐。
基于前面的思路,對于當(dāng)前的SOA管控平臺,需要考慮如何平滑的支撐Http Rest接口服務(wù)。
1. 對于新的Http Rest接口的注冊和接入
對于當(dāng)前已有的基于SOAP WS的服務(wù)規(guī)范定義文檔,最好的方式就是做到SOAP和REST接口都能給通用,雖然這樣不符合Rest面向資源的要求,也喪失了Rest接口本身的一些靈活性,但是可提升對服務(wù)規(guī)范的標(biāo)準(zhǔn)化管理。在這種模式下,對于服務(wù)規(guī)范涉及到的變化估計在于:
也就是說,我們完全可以做到一套服務(wù)規(guī)范來支撐SOAP和Rest接口,畢竟在做跨系統(tǒng)間接口服務(wù)集成的時候,這里的接口更多都是粗粒度的服務(wù)定義,并不會涉及到細粒度的數(shù)據(jù)表或?qū)ο蟮乃蠧RUD操作。跨系統(tǒng)間的接口更多的是滿足跨業(yè)務(wù)協(xié)同和數(shù)據(jù)集成需要即可,是橫向系統(tǒng)和系統(tǒng)之間的接口,而不是類似單個業(yè)務(wù)系統(tǒng)展現(xiàn)層和邏輯層到DB層的接口。
對于Http Rest接口,傳遞的數(shù)據(jù)要支持XML和Json兩種格式,這個也需要提前進行約定和配置。而為了兼容當(dāng)前的服務(wù)規(guī)范格式,可以看到這樣轉(zhuǎn)過了的Rest接口方法全部為Post接口,同時接口服務(wù)名即為資源對象名,同時在接口調(diào)用的時候傳遞的是一個我完整的數(shù)據(jù)集合對象。這和我們前面講Rest接口的設(shè)計和調(diào)用是有區(qū)別的。
規(guī)范定義講清楚后,整個過程就簡單了,原來已有的直接在界面上定義服務(wù)規(guī)范或者通過Word文檔導(dǎo)入服務(wù)規(guī)范功能基本都可以保留,做少量變更修改即可。導(dǎo)入的規(guī)范本身也可以進一步導(dǎo)出或直接在線查看。
對于Rest接口服務(wù),我們?nèi)匀豢梢宰裱粯拥钠跫s先行和自頂向下設(shè)計的思路進行。
規(guī)范清楚后,接著還是需要導(dǎo)出標(biāo)準(zhǔn)的契約格式文檔,而這里建議還是采用WADL,基于Rest接口的服務(wù)定義語言,有強契約格式要求。而對于RAML,更多是Rest接口設(shè)計建模的語言,類似于通過RAML來寫文檔。如果我們是以Word服務(wù)規(guī)范文檔格式為主,實際上是沒必要再用RAML。但是可以考慮服務(wù)規(guī)范導(dǎo)出RAML語言定義。
RAML(RESTful API Modeling Language 即 RESTful API 建模語言)是對 RESTful API的一種簡單和直接的描述。它是一種讓人們易于閱讀并且能讓機器對特定的文檔能解析的語言。這樣也方便我們后面基于RAML來生成API定義文檔。
在規(guī)范導(dǎo)出為WADL設(shè)計文件后,那么就有嚴(yán)格契約格式要求,業(yè)務(wù)系統(tǒng)可以基于該WADL定義文件,通過工具自動生成客戶端和服務(wù)端的代碼開發(fā)框架,然后再填充業(yè)務(wù)規(guī)則和邏輯,這個過程和我們標(biāo)準(zhǔn)的SOAP WS接口服務(wù)的設(shè)計和開發(fā)是一致的,并沒有太多的區(qū)別。
在服務(wù)提供端按WADL要求開發(fā)后Rest接口服務(wù)后,由ESB進行服務(wù)代理封裝接入,這個需要單獨設(shè)計功能支持,即需要采用單獨定制的OSB服務(wù)封裝模板。在服務(wù)代理接入后,我們原來對于SOAP接口的安全,日志等控制能力全部都需要保留和平滑支持。
服務(wù)代理接入后,仍然自動化部署,部署完成后給出代理封裝后的訪問地址。
對于服務(wù)調(diào)用訪問,本身也會產(chǎn)生日志記錄,對于已有的服務(wù)運行日志監(jiān)控,服務(wù)異常日志監(jiān)控等功能,都需要完全平滑的支撐Http Rest接口服務(wù)。對于原有的日志元數(shù)據(jù)配置表,服務(wù)日志運行實例表等也保留一套。
2. 對于SOAP和Rest接口本身的轉(zhuǎn)換映射問題
當(dāng)我們采用同一套規(guī)范體系的時候,我們就很容易去實現(xiàn)兩種類型接口的轉(zhuǎn)換和映射。
業(yè)務(wù)系統(tǒng)如果提供的SOAP WS接口服務(wù),我們需要單獨提供一個功能,將該SOAP WS服務(wù)發(fā)布為Http Rest接口服務(wù),同時在發(fā)布的時候可以選擇是采用XML格式,還是Json格式進行發(fā)布。
這樣好處就是原來業(yè)務(wù)系統(tǒng)以及提供了SOAP接口,但是當(dāng)我們在對接一個微服務(wù)架構(gòu)體系的時候,消費端為了自身的標(biāo)準(zhǔn)化需要消費Rest接口服務(wù),那么由ESB來完成這種轉(zhuǎn)換映射即可,原有的業(yè)務(wù)系統(tǒng)服務(wù)提供方不再需要做任何服務(wù)設(shè)計變更和代碼修改。
當(dāng)然,如果業(yè)務(wù)系統(tǒng)本身提供的Http Rest接口服務(wù),為了對已有的歷史系統(tǒng)進行支撐,我們也可以將Http Rest接口服務(wù)轉(zhuǎn)化為SOAP WS服務(wù)再進行暴露。在轉(zhuǎn)換的時候新數(shù)據(jù)格式只能夠是XML格式。
3. 對于消息發(fā)布訂閱,消息中間件的支持
對于消息發(fā)布訂閱,我們采用Weblogic JMS消息中間件,但是將JMS能力適配后發(fā)布為SOAP WS接口服務(wù)。在Http Rest接口服務(wù)實施過程中,我們需要支撐將JMS適配后能力直接發(fā)布為Rest接口服務(wù)。
當(dāng)然為了簡化,該功能非必須,即我們可以考慮在ESB接口上做兩次代理,即將ESB已經(jīng)暴露的SOAP WS消息分發(fā)服務(wù)接口,通過Http Rest接口服務(wù)轉(zhuǎn)換功能直接進行轉(zhuǎn)換后二次發(fā)布。
對于JMS消息訂閱端,本身走Java API接口進行消息消費,本身和服務(wù)采用SOAP還是Rest沒有太大關(guān)系。
4. 對于Http Rest接口的純代理接入
對于業(yè)務(wù)系統(tǒng)已有的HttpRest接口,如果不希望按嚴(yán)格的服務(wù)規(guī)范設(shè)計和契約先行的思路進行變更,我們也可以直接對已有的Rest接口進行純代理接入,即ESB做完全的代理轉(zhuǎn)發(fā),不做任何的安全控制,輸入內(nèi)容消息頭的解析,數(shù)據(jù)映射轉(zhuǎn)換等。對于這類Rest接口服務(wù),ESB總線只起代理轉(zhuǎn)發(fā)作用。
對于ESB服務(wù)總線和API網(wǎng)關(guān)產(chǎn)品來說,在前面很早的博客文章自己就談到過,整體思路是底層引擎是兩套,即一個是偏重的ESB總線引擎,一個是API網(wǎng)關(guān)引擎,但是對于SOA治理管控和運營開放則是整合為一套。一個是SOA運維監(jiān)控平臺是統(tǒng)一的一套,一個是能力開放平臺也統(tǒng)一為一套。
但是我們看到雖然ESB總線是一個偏重的引擎,但是我們不啟用其復(fù)雜的協(xié)議轉(zhuǎn)換,數(shù)據(jù)映射,服務(wù)編排等功能的時候仍然可以做為要給輕量的SOA總線來使用。而且我們看到另外一個場景,即企業(yè)很多時候不會很快就完成一個微服務(wù)架構(gòu)化的轉(zhuǎn)型,始終是存在傳統(tǒng)的遺留系統(tǒng)。
因此集成問題和場景本身是很復(fù)雜的,即使整個集成趨勢是Http Rest接口集成和API網(wǎng)關(guān)集成為主,但是你還是得兼容傳統(tǒng)觀的WS服務(wù)集成和簡單的協(xié)議轉(zhuǎn)換能力。
實際上對于ESB總線來說本身就是支持Http Rest接口服務(wù)得注冊和接入的。因此實際上對ESB服務(wù)總線和API網(wǎng)關(guān)引擎存在兩種思路可以選擇。
對于第二種方式相對來說并不會很復(fù)雜,也容易實施,即通過對ESB服務(wù)總線的升級來完成對ESB總線+API網(wǎng)關(guān)兩方面能力的完全支撐。你可以說賣的是ESB服務(wù)總線,但是完全兼容適配API網(wǎng)關(guān)所有能力。
基于上面這個思路,我們需要做的主要包括
基于以上關(guān)鍵點進行進一步的優(yōu)化和完善后,即能夠為企業(yè)提供一套完整的SOA服務(wù)總線產(chǎn)品,同時支撐傳統(tǒng)的ESB服務(wù)總線能力,又對Http Rest API接口的接入,注冊和管控方面能力得到全面增強。
歡迎關(guān)注@人月聊IT 分享SOA,微服務(wù),DevOps平臺規(guī)劃和建設(shè)。
篇 文章主要是借鑒他人,但是自己很想總結(jié)出一套規(guī)范,以供向我這樣的新手使用,用來規(guī)范代碼,如果有什么好的提議,請不吝賜教,本篇文章長期更新!
一、重要概念:
REST,即Representational State Transfer的縮寫。我對這個詞組的翻譯是"表現(xiàn)層狀態(tài)轉(zhuǎn)化"。
Resource(資源) :對象的單個實例。 例如,一只動物。它可以是一段文本、一張圖片、一首歌曲、一種服務(wù),總之就是一個具體的實在。你可以用一個URI(統(tǒng)一資源定位符)指向它,每種資源對應(yīng)一個特定的URI。要獲取這個資源,訪問它的URI就可以,因此URI就成了每一個資源的地址或獨一無二的識別符。
集合:對象的集合。 例如,動物。
第三方:使用我們接口的開發(fā)者
表現(xiàn)層(Representation)
"資源"是一種信息實體,它可以有多種外在表現(xiàn)形式。我們把"資源"具體呈現(xiàn)出來的形式,叫做它的"表現(xiàn)層"(Representation)。
狀態(tài)轉(zhuǎn)化(State Transfer)
訪問一個網(wǎng)站,就代表了客戶端和服務(wù)器的一個互動過程。在這個過程中,勢必涉及到數(shù)據(jù)和狀態(tài)的變化。互聯(lián)網(wǎng)通信協(xié)議HTTP協(xié)議,是一個無狀態(tài)協(xié)議。這意味著,所有的狀態(tài)都保存在服務(wù)器端。因此,如果客戶端想要操作服務(wù)器,必須通過某種手段,讓服務(wù)器端發(fā)生"狀態(tài)轉(zhuǎn)化"(State Transfer)。而這種轉(zhuǎn)化是建立在表現(xiàn)層之上的,所以就是"表現(xiàn)層狀態(tài)轉(zhuǎn)化"。
客戶端用到的手段,只能是HTTP協(xié)議。具體來說,就是HTTP協(xié)議里面,四個表示操作方式的動詞:GET、POST、PUT、DELETE。它們分別對應(yīng)四種基本操作:GET用來獲取資源,POST用來新建資源(也可以用于更新資源),PUT用來更新資源,DELETE用來刪除資源。
比如,文本可以用txt格式表現(xiàn),也可以用HTML格式、XML格式、JSON格式表現(xiàn),甚至可以采用二進制格式;圖片可以用JPG格式表現(xiàn),也可以用PNG格式表現(xiàn)。
URI只代表資源的實體,不代表它的形式。嚴(yán)格地說,有些網(wǎng)址最后的".html"后綴名是不必要的,因為這個后綴名表示格式,屬于"表現(xiàn)層"范疇,而URI應(yīng)該只代表"資源"的位置。它的具體表現(xiàn)形式,應(yīng)該在HTTP請求的頭信息中用Accept和Content-Type字段指定,這兩個字段才是對"表現(xiàn)層"的描述。
綜合上面的解釋,我們總結(jié)一下什么是RESTful架構(gòu):
(1)每一個URI代表一種資源;
(2)客戶端和服務(wù)器之間,傳遞這種資源的某種表現(xiàn)層;
(3)客戶端通過四個HTTP動詞,對服務(wù)器端資源進行操作,實現(xiàn)"表現(xiàn)層狀態(tài)轉(zhuǎn)化"。
二、REST接口規(guī)范
1、動作
GET (SELECT):從服務(wù)器檢索特定資源,或資源列表。POST (CREATE):在服務(wù)器上創(chuàng)建一個新的資源。PUT (UPDATE):更新服務(wù)器上的資源,提供整個資源。PATCH (UPDATE):更新服務(wù)器上的資源,僅提供更改的屬性。DELETE (DELETE):從服務(wù)器刪除資源。
首先是四個半種動作:post、delete、put/patch、get因為put/patch只能算作一類,所以將patch歸為半個。
另外還有有兩個較少知名的HTTP動詞:HEAD - 檢索有關(guān)資源的元數(shù)據(jù),例如數(shù)據(jù)的哈希或上次更新時間。OPTIONS - 檢索關(guān)于客戶端被允許對資源做什么的信息。
2、路徑(接口命名)
路徑又稱"終點"(endpoint),表示API的具體網(wǎng)址。
在RESTful架構(gòu)中,每個網(wǎng)址代表一種資源(resource),所以網(wǎng)址中不能有動詞,只能有名詞,而且所用的名詞往往與數(shù)據(jù)庫的表格名對應(yīng)。一般來說,數(shù)據(jù)庫中的表都是同種記錄的"集合"(collection),所以API中的名詞也應(yīng)該使用復(fù)數(shù)。
舉例來說,有一個API提供動物園(zoo)的信息,還包括各種動物和雇員的信息,則它的路徑應(yīng)該設(shè)計成下面這樣。
接口盡量使用名詞,禁止使用動詞,下面是一些例子。
GET /zoos:列出所有動物園 POST /zoos:新建一個動物園 GET /zoos/ID:獲取某個指定動物園的信息 PUT /zoos/ID:更新某個指定動物園的信息(提供該動物園的全部信息) PATCH /zoos/ID:更新某個指定動物園的信息(提供該動物園的部分信息) DELETE /zoos/ID:刪除某個動物園 GET /zoos/ID/animals:列出某個指定動物園的所有動物 DELETE /zoos/ID/animals/ID:刪除某個指定動物園的指定動物
反例:
/getAllCars /createNewCar /deleteAllRedCars
再比如,某個URI是/posts/show/1,其中show是動詞,這個URI就設(shè)計錯了,正確的寫法應(yīng)該是/posts/1,然后用GET方法表示show。
如果某些動作是HTTP動詞表示不了的,你就應(yīng)該把動作做成一種資源。比如網(wǎng)上匯款,從賬戶1向賬戶2匯款500元,錯誤的URI是:
POST /accounts/1/transfer/500/to/2
正確的寫法是把動詞transfer改成名詞transaction,資源不能是動詞,但是可以是一種服務(wù):
POST /transaction HTTP/1.1
Host: 127.0.0.1
from=1&to=2&amount=500.00
理清資源的層次結(jié)構(gòu),比如業(yè)務(wù)針對的范圍是學(xué)校,那么學(xué)校會是一級資源(/school),老師(/school/teachers),學(xué)生(/school/students)就是二級資源。
3、版本(Versioning)
應(yīng)該將API的版本號放入URL。如:
https://api.example.com/v1/
另一種做法是,將版本號放在HTTP頭信息中,但不如放入URL方便和直觀。Github采用這種做法。
4、過濾信息(Filtering)
如果記錄數(shù)量很多,服務(wù)器不可能都將它們返回給用戶。API應(yīng)該提供參數(shù),過濾返回結(jié)果。下面是一些常見的參數(shù)。
?limit=10:指定返回記錄的數(shù)量 ?offset=10:指定返回記錄的開始位置。 ?page_number=2&page_size=100:指定第幾頁,以及每頁的記錄數(shù)。 ?sortby=name&order=asc:指定返回結(jié)果按照哪個屬性排序,以及排序順序。 ?animal_type_id=1:指定篩選條件 參數(shù)的設(shè)計允許存在冗余,即允許API路徑和URL參數(shù)偶爾有重復(fù)。比如, GET /zoo/ID/animals 與 GET /animals?zoo_id=ID 的含義是相同的。
5、狀態(tài)碼(Status Codes)
狀態(tài)碼范圍
1xx 信息,請求收到,繼續(xù)處理。范圍保留用于底層HTTP的東西,你很可能永遠也用不到。 2xx 成功,行為被成功地接受、理解和采納 3xx 重定向,為了完成請求,必須進一步執(zhí)行的動作 4xx 客戶端錯誤,請求包含語法錯誤或者請求無法實現(xiàn)。范圍保留用于響應(yīng)客戶端做出的錯誤,例如。他們提供不良數(shù)據(jù)或要求不存在的東西。這些請求應(yīng)該是冪等的,而不是更改服務(wù)器的狀態(tài)。 5xx 范圍的狀態(tài)碼是保留給服務(wù)器端錯誤用的。這些錯誤常常是從底層的函數(shù)拋出來的,甚至 開發(fā)人員也通常沒法處理,發(fā)送這類狀態(tài)碼的目的以確保客戶端獲得某種響應(yīng)。 當(dāng)收到5xx響應(yīng)時,客戶端不可能知道服務(wù)器的狀態(tài),所以這類狀態(tài)碼是要盡可能的避免。
服務(wù)器向用戶返回的狀態(tài)碼和提示信息,常見的有以下一些(方括號中是該狀態(tài)碼對應(yīng)的HTTP動詞)。
200 OK - [GET]:服務(wù)器成功返回用戶請求的數(shù)據(jù),該操作是冪等的(Idempotent)。 201 CREATED - [POST/PUT/PATCH]:用戶新建或修改數(shù)據(jù)成功。 202 Accepted - [*]:表示一個請求已經(jīng)進入后臺排隊(異步任務(wù)) 204 NO CONTENT - [DELETE]:用戶刪除數(shù)據(jù)成功。 400 INVALID REQUEST - [POST/PUT/PATCH]:用戶發(fā)出的請求有錯誤,服務(wù)器沒有進行新建或修改數(shù)據(jù)的操作,該操作是冪等的。 401 Unauthorized - [*]:表示用戶沒有權(quán)限(令牌、用戶名、密碼錯誤)。 403 Forbidden - [*] 表示用戶得到授權(quán)(與401錯誤相對),但是訪問是被禁止的。 404 NOT FOUND - [*]:用戶發(fā)出的請求針對的是不存在的記錄,服務(wù)器沒有進行操作,該操作是冪等的。 406 Not Acceptable - [GET]:用戶請求的格式不可得(比如用戶請求JSON格式,但是只有XML格式)。 410 Gone -[GET]:用戶請求的資源被永久刪除,且不會再得到的。 422 Unprocesable entity - [POST/PUT/PATCH] 當(dāng)創(chuàng)建一個對象時,發(fā)生一個驗證錯誤。 500 INTERNAL SERVER ERROR - [*]:服務(wù)器發(fā)生錯誤,用戶將無法判斷發(fā)出的請求是否成功。 502 網(wǎng)關(guān)錯誤 503 Service Unavailable 504 網(wǎng)關(guān)超時
參考資料:
RESTful API 設(shè)計指南--阮一峰:http://www.ruanyifeng.com/blog/2014/05/restful_api.html
首先 RESTful架構(gòu),就是目前最流行的一種互聯(lián)網(wǎng)軟件架構(gòu)。它結(jié)構(gòu)清晰、符合標(biāo)準(zhǔn)、易于理解、擴展方便,所以正得到越來越多網(wǎng)站的采用。
REST這個詞,是 Roy Thomas Fielding 在他2000年的博士論文中提出的。
REST,即 Representational State Transfer 的縮寫,如果一個架構(gòu)符合REST原則,就稱它為RESTful架構(gòu)。
要理解RESTful架構(gòu),最好的方法就是去理解Representational State Transfer這個詞組到底是什么意思,它的每一個詞代表了什么涵義。如果你把這個名稱搞懂了,也就不難體會REST是一種什么樣的設(shè)計。
REST的名稱"表現(xiàn)層狀態(tài)轉(zhuǎn)化"中,省略了主語。"表現(xiàn)層"其實指的是"資源"(Resources)的"表現(xiàn)層"。
所謂"資源",就是網(wǎng)絡(luò)上的一個實體,或者說是網(wǎng)絡(luò)上的一個具體信息。它可以是一段文本、一張圖片、一首歌曲、一種服務(wù),總之就是一個具體的實在。你可以用一個URI(統(tǒng)一資源定位符)指向它,每種資源對應(yīng)一個特定的URI。要獲取這個資源,訪問它的URI就可以,因此URI就成了每一個資源的地址或獨一無二的識別符。
所謂"上網(wǎng)",就是與互聯(lián)網(wǎng)上一系列的"資源"互動,調(diào)用它的URI。
"資源"是一種信息實體,它可以有多種外在表現(xiàn)形式。我們把"資源"具體呈現(xiàn)出來的形式,叫做它的"表現(xiàn)層"(Representation)。
比如,文本可以用txt格式表現(xiàn),也可以用HTML格式、XML格式、JSON格式表現(xiàn),甚至可以采用二進制格式;圖片可以用JPG格式表現(xiàn),也可以用PNG格式表現(xiàn)。
URI只代表資源的實體,不代表它的形式。嚴(yán)格地說,有些網(wǎng)址最后的".html"后綴名是不必要的,因為這個后綴名表示格式,屬于"表現(xiàn)層"范疇,而URI應(yīng)該只代表"資源"的位置。它的具體表現(xiàn)形式,應(yīng)該在HTTP請求的頭信息中用Accept和Content-Type字段指定,這兩個字段才是對"表現(xiàn)層"的描述。
訪問一個網(wǎng)站,就代表了客戶端和服務(wù)器的一個互動過程。在這個過程中,勢必涉及到數(shù)據(jù)和狀態(tài)的變化。
互聯(lián)網(wǎng)通信協(xié)議HTTP協(xié)議,是一個無狀態(tài)協(xié)議。這意味著,所有的狀態(tài)都保存在服務(wù)器端。因此,如果客戶端想要操作服務(wù)器,必須通過某種手段,讓服務(wù)器端發(fā)生"狀態(tài)轉(zhuǎn)化"(State Transfer)。而這種轉(zhuǎn)化是建立在表現(xiàn)層之上的,所以就是"表現(xiàn)層狀態(tài)轉(zhuǎn)化"。
客戶端用到的手段,只能是HTTP協(xié)議。具體來說,就是HTTP協(xié)議里面,四個表示操作方式的動詞:GET、POST、PUT、DELETE。它們分別對應(yīng)四種基本操作:GET用來獲取資源,POST用來新建資源(也可以用于更新資源),PUT用來更新資源,DELETE用來刪除資源。
綜合上面的解釋,我們總結(jié)一下什么是RESTful架構(gòu):
(1)每一個URI代表一種資源;
(2)客戶端和服務(wù)器之間,傳遞這種資源的某種表現(xiàn)層;
(3)客戶端通過四個HTTP動詞,對服務(wù)器端資源進行操作,實現(xiàn)"表現(xiàn)層狀態(tài)轉(zhuǎn)化"。
舉例說明:對用戶表的的操作,增刪改查平衡車那個都是這么寫:
每種業(yè)務(wù)都有自己的路徑,增刪改查前端會看到四種不同的路徑,代碼整體看起來比較冗余
很明顯的區(qū)別,請求路徑統(tǒng)一,通過請求方式區(qū)分獲取、刪除、修改、保存 等動作,清爽多了
既然這么簡潔,我們實操一下吧
第1步:application.propertities 文件配置 spring.mvc.hiddenmethod.filter.enable=true,開啟表單的REST風(fēng)格支持(這個源碼分析部分會講到)
第2部:編寫一個前端頁面實測一下 REST 風(fēng)格的提交:
注意下頁面的 hidden隱藏域參數(shù)細節(jié)(后面源碼部分會提到)
點擊四個按鈕,發(fā)現(xiàn)跳轉(zhuǎn)正確!
他是怎么跳轉(zhuǎn)的,看源碼分析
SpringBoot的處理思路是:既然瀏覽器天然只能發(fā)送 GET 和 POST 請求,那可以利用前后的參數(shù)配合,根據(jù)約定好的參數(shù),把POST或者GET 定向地轉(zhuǎn)成 PUT 或 DELETE 請求
實現(xiàn)對REST 請求風(fēng)格的支持主要得益于HiddenMethodFilter 類,它同樣是在WebMvcAutoConfiguration 這個自動配置類中在項目啟動時自動注入的。
著重看一下 HiddenHttpMethodFilter ,顧名思義 隱藏HTTP方法過濾器,它的類注釋翻譯完粘貼過來:
由于瀏覽器目前僅支持 GET 和 POST,因此一種常用技術(shù)(例如 Prototype 庫使用的技術(shù))是使用帶有附加隱藏表單字段 ( _method ) 的普通 POST 來傳遞“真正的”HTTP 方法。 此過濾器讀取該參數(shù)并相應(yīng)地更改HttpServletRequestWrapper.getMethod()返回值。 只允許"PUT" 、 "DELETE"和"PATCH" HTTP 方法。
請求參數(shù)的名稱默認(rèn)為_method ,但可以通過methodParam屬性進行調(diào)整。
看下 HiddenHttpMethodFilter 的核心方法 doFilterInternal() , 他是如何吧我們的隱藏表單解析的
如何獲取?
轉(zhuǎn)發(fā)分享此文,后臺私信小編:“666”即可獲取。(注:轉(zhuǎn)發(fā)分享,感謝大家)
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。