HAL 與 HATEOAS 的關係與區別

Architecture,REST,Web Services
Remote
1
02:54 AM · Dec 01 ,2025

1. 概述

Web API 隨着 REST (表意層傳輸) 的興起而迅速發展。基於 REST 的 API 允許開發者構建模塊化、標量化且鬆散耦合的強大 Web 應用程序。雖然 RESTful API 提供了一個堅實的基礎,但它們通常缺乏可發現性和可用性的基本要素。

正是在這裏,HATEOAS (狀態為引擎的超媒體) 和 HAL (超文本應用程序語言) 可以產生重大影響。 在沒有 HATEOAS 的情況下,RESTful API 會與服務器緊密耦合,需要在客户端側硬編碼端點。

在本教程中,我們將探索 HATEOAS 和 HAL 的概念、它們之間的關係以及它們的主要區別。

2. 理解 HATEOAS

HATEOAS 代表 Hypermedia 作為應用程序狀態的引擎。 為了更深入地理解這個概念,我們首先需要理解 Hypermedia 的含義。 Hypermedia 是超文本的擴展,它包含文本鏈接和其他媒體類型,例如圖像、音頻和視頻。 它允許通過啓用用户無縫地導航相關資源來實現豐富的交互。

HATEOAS 通過在響應中嵌入 Hypermedia 鏈接來增強 API 交互。 這使客户端能夠在無需先了解 API 結構的情況下,動態地導航和與資源進行交互。 它促進鬆散耦合,並允許 API 在獨立地演變。

這意味着客户端-服務器交互應該完全依賴於服務器響應中收到的 Hypermedia。 每次服務器響應都包含鏈接,以指導客户端發現有關其他操作和資源的更多信息以及數據。

讓我們通過購物車的例子來更深入地瞭解 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 是一個具體的格式,通過標準化如何表示資源及其連接 via 鏈接來幫助實現它。

讓我們以早先討論的購物車的例子為例。 當客户端請求有關包含項目的購物車的詳細信息時,服務器會返回一個 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 HAL
概念/格式 HATEOAS 是一種 REST 架構原則,它指導客户端通過遵循服務器提供的超媒體鏈接來發現可用的操作。 HAL 是一種用於以支持 HATEOAS 的方式表示資源的特定格式。
目的 HATEOAS 的目的是使 API 具有自我解釋性,並易於導航。它減少了客户端需要先了解 API 結構的需求。 HAL 提供了一種清晰簡潔的方式來表示資源及其連接。它簡化了客户端對鏈接的解析和理解。
實現 各種格式和技術,例如 JSON、XML,甚至 HAL 本身,都可以實現 HATEOAS。 HAL 專門使用 JSON 或 XML 結構化資源表示,強調鏈接。

6. 結論

在本文中,我們討論了 HATEOAS 和 HAL。 雖然 HATEOAS 闡明瞭 RESTful API 應該如何運行的原則,但 HAL 提供了一個具體的實現,簡化了 API 中的超媒體控件。 使用 HAL,開發人員可以輕鬆創建符合 HATEOAS 的 API,從而簡化了客户端對資源的發現和交互。

通過結合 HATEOAS 和 HAL,API 變得自描述且易於發現。 這導致客户端和服務器之間更好地解耦,允許 API 在一段時間內獨立演進。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.