API接口架構REST vs GraphQL(api接口和restful接口)
無論是創(chuàng)建網(wǎng)站,還是移動應用程序,我們都需要通過 API 來傳遞數(shù)據(jù),通過 API 我們可以獲取到數(shù)據(jù)庫中的數(shù)據(jù),可以操作數(shù)據(jù)庫,可以處理一些業(yè)務邏輯?,F(xiàn)在最流行的 API 架構是 REST。但是,GraphQL 正在逐漸追趕著它。
GraphQL 是一種新型的 API 架構,它比 REST 更靈活、更高效,并且具有聲明式數(shù)據(jù)獲取等功能。雖然 GraphQL 正在變得非常流行,但它并沒有取代 REST,因為一些用戶發(fā)現(xiàn)它更難使用,并認為它是一個過度設計的解決方案,尤其是對于一些小型項目。
REST
現(xiàn)代應用程序開發(fā)中 API 的主要架構是 REST。大多數(shù)后端框架可以非常容易地實現(xiàn) REST。REST API 通常通過 HTTP 方法被調(diào)用。通過訪問一個 URL, 就實現(xiàn)了對接口的調(diào)用處理。
REST 案例
假設你正在創(chuàng)建一個博客站點, 在首頁上,你會顯示最新文章的摘要,包括標題、圖片和簡短描述。為了提供這些數(shù)據(jù),你需要在后端服務器上查詢數(shù)據(jù)庫或者緩存來獲取結果。然后一個 REST API 就完成了 GET/api/articles,它以 JSON 數(shù)組的形式返回所需的數(shù)據(jù),如下例所示:
// GET /articles[{"id": 1,"title": "REST is Awesome","image": "https://restblog.com/img/dsh9a89.png","description": "The benefits of REST"},{"id": 2,"title": "How REST Works","image": "https://restblog.com/img/33szad2.png","description": "Learn about REST"}]
REST 的優(yōu)點
方便實現(xiàn)
在 Web 服務器應用程序中設置 REST 很簡單,尤其是當我使用一些框架的時候。比如laravel,express,django,springboot 等,它們都提供了非常方便的方法來實現(xiàn) REST 接口。
例如,/api/articles 使用 MongoDB 在 Express 應用程序中設置 REST 接口非常簡單:
app.get('/api/articles', async (req, res) => {try {const articles = await db.articles.find() res.json(articles)} catch (err) {res.status(500).send(err)}})
通俗易懂
REST 很好理解,基本上通過請求方法和請求參數(shù)還有接口名稱,我們就知道這個接口的作用,并且無論是前端人員還是后臺人員都可以非常容易地通過接口文檔進行數(shù)據(jù)的交互。
REST 的缺點
冗余數(shù)據(jù)
回到博客的例子,假設我們在創(chuàng)建 PC 站點的同時,也創(chuàng)建了一個移動網(wǎng)站。和桌面版本一樣,在移動端的首頁我們也要顯示文章摘要。由于手機屏幕尺寸較小,這里的摘要只需要標題和圖片,可以省略描述。
但不幸的是,由于/api/articles 接口是固定的,所以移動端的 description 在調(diào)用 API 是否仍然會收到該字段。
這些冗余數(shù)據(jù)在頻繁調(diào)用和發(fā)送大量數(shù)據(jù)的時候會造成服務器的資源浪費。
嵌套數(shù)據(jù)
有些時候我們通過一個接口要返回更多的數(shù)據(jù)的時候,我們就會使用嵌套數(shù)據(jù)。
例如,我們可能需要一個帶有嵌套評論的文章。我們在獲取到文章的時候,還需要再通過文章id獲取評論信息。這就會導致請求時間的延長。
GraphQL
REST 數(shù)據(jù)冗余和低效率,促使 Facebook 工程師在 2015 創(chuàng)建了一種新的 API 設計模式,稱為 GraphQL。與 REST 一樣,GraphQL 不是特定的軟件,而是 API 設計的規(guī)范。
GraphQL 的工作原理
為了了解 GraphQL 的優(yōu)勢,我們將快速概述它的工作原理。與 REST 不同,GraphQL 需要一個模式來告訴客戶端和服務器通過 API 允許哪些數(shù)據(jù)和操作。這些是用 GraphQL 模式是語言定義的,它是一種與語言無關的具有強大的類型系統(tǒng)的格式。
GraphQL 例子
讓我們回到獲取文章和評論的例子中。在我們的 GraphQL 模式中,我們將定義Article類型,該類型具有必需的整數(shù)id字段和用于title、image和可選字符串字段description,如下所示:
type Article { id: Integer! title: String image: String description: String}
除了基本的標量類型之外,模式對象還可以相互引用。我們可以在類型和類型之間創(chuàng)建一對多的關系Comment,如下所示:
type Article { id: Integer! title: String image: String description: String comments: [Comment]}type Comment { content: String article: Article author: Author}
定義操作
GraphQL 模式的另一個重要用途是定義操作,包括讀取數(shù)據(jù)的查詢和寫入數(shù)據(jù)。在這里,我們提供了一個查詢Articles:
type Article { id: Integer! title: String image: String description: String comments: [Comment]}type Comment { content: String article: Article author: Author}type Query { articles: [Article]}
GraphQL 的優(yōu)點
聲明式數(shù)據(jù)獲取
GraphQL 殺手級功能是聲明式數(shù)據(jù)獲取,客戶端可以在其中準確指定它需要的數(shù)據(jù)。這可以包括特定字段,甚至在嵌套對象中。我們之前看到必須在模式上定義操作。但是,在這些操作中,我們可以指定我們希望查詢返回到模式限制的哪些字段。
例如,我們可以創(chuàng)建一個查詢,Articles只獲取我們想要的字段,無論是否嵌套Comments。請參見下面的示例:
query { articles { id title image description comments { content } }}
這是將從該查詢返回的數(shù)據(jù)結構。請注意,在 GraphQL 響應中接收到的數(shù)據(jù)將與請求它的查詢具有相同的結構。
{"data": {"articles": [{"id": 1,"title": "REST is Awesome","image": "https://restblog.com/img/dsh9a8.png","description": "An article about REST","comments": [{"content": "GraphQL is better!"}]}}
通過這種方式,GraphQL 消除了冗余數(shù)據(jù)和嵌套數(shù)據(jù)問題。
健壯性
由于強類型和預定義查詢的要求,GraphQL 可以提供開箱即用的驗證和類型檢查。反過來,這意味著 GraphQL 本質(zhì)上是自記錄的。一旦字段、類型或查詢發(fā)生更改,基于架構的文檔可以自動更新。
沒有版本控制的 API
每次應用更改時,API 可能也需要更改。例如,假設我們決定將實體中的description字段重命名的時候.
REST 通過提供多個版本來處理這個問題,這對于 API 開發(fā)人員來說是很麻煩的。
使用 GraphQL,可以從模式中刪除不推薦使用的字段,而不會影響現(xiàn)有查詢。這為應用程序提供了對新功能的持續(xù)訪問,并鼓勵更清潔、更可維護的代碼。
GraphQL 的缺點
矯枉過正
一些開發(fā)人員認為 GraphQL 解決的問題通常被夸大了。例如,對于大多數(shù)小型應用程序來說,因為幾個字節(jié)的冗余數(shù)據(jù)而設計的更加復雜,這可能并不劃算。
難于學習
GraphQL 比 REST 更難于實現(xiàn),它為新用戶提供了更難的學習曲線。
難以緩存
GraphQL 經(jīng)常被批評為更難緩存。REST 客戶端受益于 HTTP 緩存,因為所有端點都是 URL,而 GraphQL 客戶端需要實現(xiàn)自己的自定義解決方案。
總結
雖然 REST 架構在過去十年中主導了 Web 開發(fā),但它對接口調(diào)用的的使用使其在某些情況下有些不靈活且效率低下。GraphQL 通過提供嚴格類型化的模式語言來解決這些問題,接口調(diào)用者可以根據(jù)自己的需要進行查詢。
如果未來能有更好的設計將兩者的優(yōu)點結合,我相信會是最佳的解決方案。