定义资源
在Fielding的論文中 ,資源被描述為:
“可以命名的任何信息”……“文檔或圖像,臨時服務(wù)(例如,“洛杉磯今天的天氣”),其他資源的集合,非虛擬對象(例如,人) 等等。 換句話說,任何可能成為作者超文本 引用 目標(biāo)的概念都 必須符合資源的定義。 資源是 到一組實(shí)體 的概念性映射 ,而不是在任何特定 時間 點(diǎn)對應(yīng)于該映射的實(shí)體 。”
定義資源既是科學(xué)也是藝術(shù) 。 它需要領(lǐng)域知識和API體系結(jié)構(gòu)技能。 下面詳細(xì)介紹的以下幾點(diǎn)用作清單,可以幫助您確定資源。
資源必須包含業(yè)務(wù)說明
- 商業(yè)描述應(yīng)為簡單散文中的3-4個句子,以說明資源是什么。
- 對您的系統(tǒng)有一定了解的開發(fā)人員應(yīng)該能夠理解該描述
- 資源的任何警告均應(yīng)明確
資源應(yīng)單獨(dú)使用
這類似于定義微服務(wù)邊界的準(zhǔn)則,在這種情況下,應(yīng)將微服務(wù)視為自身有用。 同樣,資源應(yīng)單獨(dú)使用。
例如,代替:
/street-address/{id} RESPONSE { "street1" : "String" , "street2" : "String" }和
/address-extra/{id} RESPONSE { "city" : "String" , "country" : "String" }它應(yīng)該是:
/address/{id} RESPONSE { "street1" : "String" , "street2" : "String" , "city" : "String" , "country" : "String" }如果資源本身沒有用,并且總是需要后續(xù)請求,則意味著代碼將不可避免地變得更加復(fù)雜,并且第二個請求將對性能造成影響
使用適當(dāng)?shù)拿~
最好使用簡單名詞而不是復(fù)合名詞。 例如,
地址優(yōu)于AddressInfo或AddressDetail 。 這是一條一般規(guī)則,總會有例外 。
如果使用多個資源表示同一數(shù)據(jù)的不同視圖,例如: Address和AddressDetail ,則使用簡單名詞,例如
地址第一。 然后,如果第二種表示形式更詳細(xì)地使用
ResourceNameDetail,或者如果不夠詳細(xì),請使用ResourceNameSummary 。 例如,假設(shè)需要引入一個地址類型資源:
如果僅在READ中使用它,它是否需要成為資源?
如果僅在讀取請求中使用過資源,而從未在寫入 ( 創(chuàng)建,部分更新,完全更新,刪除等 )請求中使用過資源,則是否需要將其定義為具有自己的URI的資源是可疑的。 可以將其添加到父負(fù)載中,如果擔(dān)心負(fù)載會變得太復(fù)雜,則父可以僅提供一個稀疏查詢-客戶端可以根據(jù)API請求確定要返回的內(nèi)容。
資源應(yīng)符合統(tǒng)一接口
統(tǒng)一的接口是良好API設(shè)計的重要組成部分。 如果創(chuàng)建,讀取,更新,刪除等操作以一致的方式進(jìn)行,則意味著代碼更加一致,可重用且更易于維護(hù)。
這表示:
GET /addresses/{id}和
GET /addresses必須返回相同的地址數(shù)據(jù)結(jié)構(gòu)來表示一個地址。
GET /addresses/{id} RESPONSE { "id" : "546" , "street1" : "String" , "street2" : "String" , "city" : "String" , "country" : "String" }和
GET /addresses RESPONSE { "elements" : [ { "id" : "546" , "street1" : "String" , "street2" : "String" , "city" : "String" , "country" : "String" }, ... ] }同樣,對于寫入有效負(fù)載,數(shù)據(jù)結(jié)構(gòu)應(yīng)該相同。 因此,更改street1的部分更新將是:
POST /addresses/{id}/edit REQUEST { "street1" : "Walkview" } RESPONSE { "id" : "546" , "street1" : "Walkview" , "street2" : "Meadowbrook" , "city" : "Dublin" , "country" : "Ireland" }而不是像
POST /addresses/{id} REQUEST { "newStreet1Value" : "Walkview" }從資源的角度來看,數(shù)據(jù)結(jié)構(gòu)必須一致。 不同的數(shù)據(jù)結(jié)構(gòu)意味著不同的資源,應(yīng)使用不同的名稱命名并具有自己的路徑。
不要暴露一切
如果您的數(shù)據(jù)庫模型非常復(fù)雜,則不需要在API級別公開所有屬性。 有些字段只能保留用于后臺處理,而不能顯示在UI上。 此類屬性永遠(yuǎn)不應(yīng)包含在JSON API中。
在將屬性添加到JSON資源時,請考慮:
- API中應(yīng)僅公開您確定客戶端感興趣的字段
- 如果不確定,請忽略該屬性。 稍后添加屬性,然后刪除已經(jīng)公開的屬性的風(fēng)險要低得多。
API模型不應(yīng)盲目地反映數(shù)據(jù)庫關(guān)系模型或OO模型
在數(shù)據(jù)庫建模方法中,使用規(guī)范化數(shù)據(jù)或折疊繼承層次結(jié)構(gòu)。 在面向?qū)ο蟮脑O(shè)計中,諸如多態(tài),繼承層次結(jié)構(gòu)等技術(shù)被用于促進(jìn)諸如代碼重用之類的事情并減少耦合。
資源建模不必遵循這些技術(shù)。 API的使用者不關(guān)心數(shù)據(jù)是全部放在一個表中還是在多個表中進(jìn)行了規(guī)范化。 通常,API以易于使用的格式返回數(shù)據(jù),并且在客戶端變得有用之前不需要客戶端進(jìn)行太多其他映射。
使用分層數(shù)據(jù)避免重復(fù)
與諸如CSV之類的平面格式相比,分層數(shù)據(jù)的優(yōu)點(diǎn)之一是它提供了一種避免重復(fù)的機(jī)制。 例如,考慮一個數(shù)據(jù)結(jié)構(gòu),其中包含人員列表以及他們所在的團(tuán)隊(duì)。在CSV中,這是:
team, firstname, lastname Liverpool, Mo, Salah Liverpool, Andy, Roberston在JSON中,可能是:
{ "team" : "Liverpool" , "players" : [ { "firstName" : "Mo" , "lastName" : "Salah" }, { "firstName" : "Andy" , "lastName" : "Roberston" }, ... ] }使用分層數(shù)據(jù)使上下文清晰
分層數(shù)據(jù)的另一個優(yōu)點(diǎn)是它有助于提供上下文。 要了解平面數(shù)據(jù)結(jié)構(gòu),您需要了解生成數(shù)據(jù)結(jié)構(gòu)的查詢是什么,以了解其含義。 例如,考慮一堆包含日期范圍的行。
name, fromDate, toDate, holidays Tony, 2018 - 01 - 01 , 2018 - 02 - 02 , true Tony, 2018 - 02 - 03 , 2018 - 03 - 01 , false您可以假設(shè)當(dāng)Tony休假時會有新的一行。 但是如果還有另一列怎么辦
name, fromDate, toDate, holidays, sick, Tony, 2018 - 01 - 01 , 2018 - 02 - 02 , true , false Tony, 2018 - 02 - 03 , 2018 - 03 - 01 , false , true日期范圍是否對應(yīng)于假期,疾病或兩者兼而有之?
如果我們能獲得更多數(shù)據(jù),也許會更清楚……
name, fromDate, toDate, holidays, sick, Tony, 2018 - 01 - 01 , 2018 - 02 - 02 , true , false Tony, 2018 - 02 - 03 , 2018 - 03 - 01 , false , true Tony, 2018 - 03 - 02 , 2018 - 04 - 01 , false , false現(xiàn)在看來,日期范圍所對應(yīng)的是一種病,這只是一個巧合,它排列了一個假期。 但是,當(dāng)我們獲得更多數(shù)據(jù)時,此理論將失敗:
name, fromDate, toDate, holidays, sick, Tony, 2018 - 01 - 01 , 2018 - 02 - 02 , true , false Tony, 2018 - 02 - 03 , 2018 - 03 - 01 , false , true Tony, 2018 - 03 - 02 , 2018 - 04 - 01 , false , false Tony, 2018 - 04 - 02 , 2018 - 05 - 01 , true , false平面數(shù)據(jù)結(jié)構(gòu)的問題在于,只能使數(shù)據(jù)自我描述。 如果沒有任何信息,它將變得更加復(fù)雜。 例如:
name, fromDate, toDate, holidays, sick, Tony, 2018 - 01 - 01 , 2018 - 02 - 02 , true , false Tony, 2018 - 02 - 03 , 2018 - 03 - 01 , false , true Tony, 2018 - 03 - 02 , 2018 - 04 - 01 , false , false Tony, 2018 - 04 - 02 , 2018 - 05 - 01 , true , false Tony, 2018 - 05 - 02 , 2018 - 06 - 01 , null , false Tony, 2018 - 06 - 02 , 2018 - 07 - 01 , null , false Tony, 2018 - 07 - 02 , 2018 - 07 - 08 , true , false Tony, 2018 - 07 - 08 , 2018 - 07 - 09 , true , null不可避免的是,處理該數(shù)據(jù)將是錯誤的。 我們可以用以下分層格式表示相同的數(shù)據(jù):
{ "name" : "tony" , "holidays" : [ { "fromDate" : "fromDate" "2018-01-01" , "toDate" : "2018-02-02" }, { "fromDate" : "fromDate" "2018-04-02" , "toDate" : "2018-05-01" }, { "fromDate" : "2018-07-02" , "toDate" : "2018-07-09" } ], "sick" : [ { "fromDate" : "2018-02-03" , "toDate" : "2018-03-01" } ] }現(xiàn)在,數(shù)據(jù)更加自我描述。 很清楚,日期范圍是假期還是病假。
資源關(guān)系
資源本身只能描述自己。 資源模型描述資源之間的關(guān)系。 這將表明:
- 資源之間的依賴關(guān)系。 存在特定資源需要哪些資源,或者當(dāng)特定資源發(fā)生更改時會影響哪些資源:更新或刪除。
- 數(shù)據(jù)導(dǎo)航–在大域模型中,如果向模型的使用者提供導(dǎo)航和方向感,則更容易理解和遵循。 尤其是何時進(jìn)行導(dǎo)航(資源松散連接)與向下導(dǎo)航(資源牢固連接)可以區(qū)分開
資源不僅應(yīng)該考慮實(shí)現(xiàn)HATEOAS的超媒體鏈接; 當(dāng)資源使用超媒體鏈接描述它們所鏈接的內(nèi)容時,它是表達(dá)資源模型的一種非常強(qiáng)大的機(jī)制。 優(yōu)勢包括:
- 它將大型域模型分成更易于管理的部分。 通常,用戶只對模型的特定部分感興趣。 當(dāng)“資源”自己描述自己的關(guān)系時,這意味著將一個大型的復(fù)雜模型分解為易于消化的部分,并且用戶可以更快地獲取所需的信息。
- 資源模型是自我描述的,并與代碼保持同步。 一切都在同一地點(diǎn)。
明確父母與子女的關(guān)系
子級自我描述了父級URL層次名稱間距。 父資源具有一種或多種類型的子代,應(yīng)通過提供指向子代的鏈接來闡明這一點(diǎn)。 例如,如果一個團(tuán)隊(duì)有一個玩家。 團(tuán)隊(duì)有效負(fù)載應(yīng)對此進(jìn)行明確說明。
明確對等關(guān)系
這與上面的類似,只不過它用于存在于不同層次名稱空間中的資源。 因此,例如,假設(shè)團(tuán)隊(duì)在部門1中。應(yīng)該在團(tuán)隊(duì)的部門屬性中包含一個鏈接。
REQUEST https: //api.server.com/teams/4676 RESPONSE { "id" : "34533" , "division" : { "name" : "Division 1" , "_links" : { "self" : " https://api.server.com/divisions/1 " } }, ..., "_links" : { "self" : " https://api.server.com/teams/4676 " , "players" : " https://api.server.com/teams/4676/players " } }明確鏈接到其他表示形式
如果將數(shù)據(jù)建模為具有多個代表數(shù)據(jù)不同表示形式的資源,則這些資源還應(yīng)包括彼此的鏈接。
REQUEST https: //api.server.com/teams/4676 RESPONSE { "id" : "34533" , "division" : { "name" : "Division 1" , "_links" : { "self" : " https://api.server.com/divisions/1 " } }, ..., "_links" : { "self" : " https://api.server.com/teams/4676 " , "players" : " https://api.server.com/teams/4676/players " , "teamDetails" : " https://api.server.com/teamDetails/4676 " } }翻譯自: https://www.javacodegeeks.com/2019/06/defining-resource.html
總結(jié)
- 上一篇: iPhone 15国行版相比美版原来&l
- 下一篇: 特斯拉Model 3焕新版有望下月开始在