HAL 和 HATEOAS 的關係和區別
1. 概述
隨著 REST(表述性狀態傳輸)的興起,Web API 迅速發展。基於 REST 的 API 允許開發人員建立強大的模組化、標量和鬆散耦合的 Web 應用程式。雖然 RESTful API 提供了堅實的基礎,但它們通常缺乏可發現性和可用性的基本要素。
這就是 HATEOAS(超媒體作為應用程式狀態引擎)和 HAL(超文本應用程式語言)可以發揮重大作用的地方。如果沒有 HATEOAS,RESTful API 就會與伺服器緊密耦合,需要在客戶端進行硬編碼端點。
在本教程中,我們將探討 HATEOAS 和 HAL 的概念、它們的關係以及它們的主要差異。
2. 了解 HATEOAS
HATEOAS 代表超媒體作為應用程式狀態引擎。為了深入探討這個概念,我們首先需要了解超媒體的涵義。超媒體是超文本的擴展,包括文字連結和其他媒體類型,例如圖像、音訊和視訊。它使用戶能夠無縫地導航相關資源,從而實現豐富的互動。
HATEOAS 透過在回應中嵌入超媒體連結來增強 API 互動。這使得客戶端能夠動態地導航資源並與資源交互,而無需事先了解 API 的結構。它促進鬆散耦合並允許 API 隨著時間的推移而獨立發展。
這意味著客戶端-伺服器互動應該完全依賴伺服器回應中接收到的超媒體。來自伺服器的每個回應都包含指導客戶端發現其他操作和資源以及資料的連結。
讓我們透過購物車範例來了解更多 HATEOAS:
當客戶端請求有關包含商品的購物車的詳細資訊時,伺服器會提供可能操作的相關連結:
GET /cart/12345 HTTP/1.1
HTTP/1.1 200 OK
{
"cartId": 12345,
"items": [
{
"id": 001,
"name": "TV",
"qty": 1,
"amount": 4750
}
],
"totalAmount": 4750,
"links": [
{
"rel": "self",
"href": "/cart/12345"
},
{
"rel": "addItem",
"href": "/cart/12345/add"
},
{
"rel": "removeItem",
"href": "/cart/12345/remove"
},
{
"rel": "checkout",
"href": "/cart/12345/checkout"
},
{
"rel": "clear",
"href": "/cart/12345/clear"
}
]
}
在上面的範例中,客戶可以新增或刪除更多商品、繼續結帳或清除購物車。所有這些操作均基於購物車中的可用商品。 links
鍵指示可用的操作。 現在,讓我們考慮一個空購物車的範例:
GET /cart/987 HTTP/1.1
HTTP/1.1 200 OK
{
"cartId": 987,
"items": [],
"totalAmount": 0.0,
"links": [
{
"rel": "self",
"href": "/cart/987"
},
{
"rel": "addItem",
"href": "/cart/987/add"
},
{
"rel": "checkout",
"href": "/cart/987/checkout"
},
]
}
現在,客戶端可用的操作受到限制。客戶可以將商品添加到購物車或繼續結帳,但他們無法清除或刪除商品,因為購物車已經是空的。這個超文本告訴我們什麼是允許的,什麼是不允許的。
3. 理解HAL
HAL 是一種簡單的格式,可協助開發人員為 RESTful API 建立超媒體表示,支援 HATEOAS 原則。它定義了一種簡單的格式,為 REST API 中的資源之間的超連結提供了一種簡單、一致的方式。
讓我們來看看HAL的關鍵概念。
3.1.連結
HAL 允許在資源表示中包含超媒體連結。 _links
屬性列出了與資源相關的連結。每個連結都包含一個rel
(關係類型)和一個href
,客戶端可以使用它們與 API 互動。 _links
屬性還包含一個自鏈接,允許客戶端直接存取當前資源。
3.2.嵌入式資源
顧名思義,嵌入式資源表示其他資源包含在給定的 REST 資源中。 _embedded
屬性可以保存相關資源。這允許客戶端存取相關資訊而無需提出任何其他請求。
3.3.狀態
HAL 使用 JSON 或 XML 對資源資料和關聯連結進行編碼。
現在,讓我們看一個沒有 HAL 的範例,其中 API 的回應將如下所示:
{
"cartId": 12345,
"items": [
{
"id": 001,
"name": "TV",
"qty": 1,
"amount": 4750
}
]
}
上面的範例沒有提供任何相關資源的連結。現在,我們將向回應添加 HAL 鏈接,使其成為符合 HAL 的範例:
{
"_embedded": {
"items": [
{
"id": 001,
"name": "TV",
"qty": 1,
"amount": 4750,
"_links": {
"self": { "href": "/items/001" },
"update": { "href": "/items/001/update" }
}
}
]
},
{
"_links": {
"self": { "href": "/carts/12345" },
"addItem": { "href": "/cart/12345/item" },
"checkout": { "href": "/cart/12345/checkout" }
}
}
}
在上面的範例中,主要資料位於_embedded
屬性下。在這裡,主要數據包含購物車中的商品列表,每個商品都有自己的_links.
4. HATEOAS與HAL的關係
HATEOAS 和 HAL 在 RESTful API 設計方面是密切相關的概念。 HATEOAS 是 REST 的一項原則,鼓勵使用超媒體連結讓客戶端動態探索 API。另一方面,HAL 是一種特定格式,它透過標準化如何表示資源及其透過連結的連結來幫助實現這一點。
讓我們看一下前面討論的購物車範例。當客戶端要求有關包含商品的購物車的詳細資訊時,伺服器會使用 HAL 表示回應:
GET /cart/12345 HTTP 1.1
HTTP/1.1 200 OK
{
"cartId": 12345,
"items": [{
"id": 001,
"name": "TV",
"qty": 1,
"amount": 4500
}],
"totalAmount": 4500,
"_links": {
"self": { "href": "/cart/12345", "rel": "self" },
"addItem": { "href": "/cart/12345/add", "rel": "addItem"},
"checkout": { "href": "/cart/12345/checkout", "rel": "checkout" },
"clear": { "href": "/cart/12345/clear" , "rel": "clearCart" }
},
"_embedded": {
"offer": {
"code": "DISCOUNT10",
"discount": 10
}
}
在上面的範例中, _links
部分提供了超媒體鏈接,描述客戶端可以根據當前資源的狀態採取的操作。 rel
欄位很重要,因為它定義了連結所代表的操作(例如self, addItem, checkout,
等)。它用於描述連結的含義以及客戶端應如何在 API 狀態的上下文中解釋它。
_embedded
部分包含直接嵌入到主資源中的相關資源。它允許客戶端在不發出額外請求的情況下存取相關數據,減少網路呼叫並提高效率。
資源的狀態是在回應返回的實際資料中捕獲的,例如商品和購物車的總量。
5. HATEOAS 和 HAL 之間的主要區別
讓我們來看看 HATEOAS 和 HAL 之間的主要區別:
方面 | 哈特奧阿斯 | 哈爾 |
---|---|---|
概念/形式 | HATEOAS 是一種 REST 架構原則,指導客戶端透過追蹤伺服器提供的超媒體連結來發現可用的操作。 | HAL 是一種特定格式,用於以支援 HATEOAS 的方式表示資源。 |
目的 | HATEOAS 的目的是讓 API 不言自明且易於導航。它減少了客戶預先了解 API 結構的需要。 | HAL 提供了一種清晰簡潔的方式來表示資源及其連結。它簡化了客戶端解析和理解連結的過程。 |
執行 | 各種格式和技術,例如 JSON、XML,甚至 HAL 本身,都可以實現 HATEOAS。 | HAL 專門使用 JSON 或 XML 建立資源表示,強調連結。 |
六、結論
在本文中,我們討論了 HATEOAS 和 HAL。 HATEOAS 概述了 RESTful API 應如何運作的原則,而 HAL 則提供了簡化 API 中超媒體控制的具體實作。使用 HAL,開發人員可以輕鬆建立符合 HATEOAS 的 API,從而簡化客戶端的資源發現和互動。
透過結合 HATEOAS 和 HAL,API 變得具有自描述性和可發現性。這會導致客戶端和伺服器之間更好的解耦,從而允許 API 隨著時間的推移獨立發展。