官术网_书友最值得收藏!

4.2.1 HATEOAS和HAL

要使用Spring HATEOAS,我們首先需要理解什么是HATEOAS,而要解釋HATEOAS這個概念先要解釋什么是超媒體。接下來,我們就從超媒體開始講起。

1. HATEOAS

我們已經知道什么是多媒體(Multimedia),以及什么是超文本(Hypertext)。其中超文本特有的優勢是擁有超鏈接(Hyperlink)。如果我們把超鏈接引入到多媒體中,那就得到了超媒體(Hypermedia),因此這里的關鍵角色還是超鏈接。從HATEOAS的字面上進行理解,使用超媒體作為應用狀態的引擎,指的就是應用的狀態變更將由客戶端訪問不同的超媒體資源來驅動。這個概念聽起來有點復雜,讓我們通過一個簡單的示例來進行理解,如代碼清單4-42所示。

代碼清單4-42 超媒體示例代碼

//請求
GET  https://api.example.com/profile
//響應
{
    "name": "tianyalan",
    "picture": {
        "large": "https://somecdn.com/pictures/1200x1200.png",
        "medium": "https://somecdn.com/pictures/100x100.png",
        "small": "https://somecdn.com/pictures/10x10.png"
    }
}

可以看到,上述響應結果包含了鏈接地址,因此使用該API的客戶端就能夠自由選擇要下載的具體圖片。這些鏈接告知了客戶端有哪些可供選擇的圖片,以及它們的地址在哪里。這樣一來,客戶端就能夠根據不同的場景,做出符合自身需要的選擇。而且,如果客戶端只需要一種格式的圖片,那就無須下載全部三種版本的圖片。因此,這種表現形式有很多優勢,既減少了網絡負載,又提高了客戶端的靈活性,更增進了API的可探索性。

HATEOAS的重要性在于打破了客戶端和服務器之間嚴格的契約,使得客戶端可以更加智能和自適應,而RESTful服務本身的演化和更新也變得更加容易。我們知道在使用普通的RESTful API時,客戶端需要根據服務器提供的相關文檔來了解所暴露的資源和對應的操作。而基于HATEOAS的RESTful API可以實現服務端和客戶端的解耦,客戶端通過服務器提供的資源來智能地發現可執行操作,這就是所謂的自解釋Web API。

2. HAL

HATEOAS更多是一種概念,而HAL(Hypertext Application Language,超文本應用語言)是HATEOAS的一種實現方式。與普通的RESTful風格不同,對每個資源,HAL又將其細分成狀態(State)、鏈接(Links)和子資源(Embedded Resource)三個標準部分,如圖4-4所示。

097-1

圖4-4 HAL模型結構

這里的資源狀態是指資源本身固有的屬性,鏈接定義了與當前資源相關的一組資源的鏈接集合,而子資源則描述當前資源的具體內容,提供嵌套資源的定義。

舉例來說,在不使用HAL的場景下,我們設計一個RESTful風格的API一般會采用如代碼清單4-43所示的表現形式。

代碼清單4-43 RESTful風格請求和響應示例代碼

//請求
GET http://api.example.com/users/tianyalan
//響應
Content-Type: application/json
{
    "id": "user1",
    "name": "tianyalan",
    "email": "tianyalan@email.com"
}

而為了讓API返回的數據更具有關聯性,我們使用HAL+JSON格式,這時候返回的格式就會變成如代碼清單4-44所示的表現形式。注意到這里多了_links屬性,其中有一個self.href鏈接指向當前user資源。

代碼清單4-44 HAL+JSON風格請求和響應示例代碼

//請求
GET  http://api.example.com/users/tianyalan
//響應
Content-Type: application/json
{
    _links: {
        self: {
        href: "/users/tianyalan"
        }
    }
    "id": "user1",
    "name": "tianyalan",
    "email": "tianyalan@email.com"
}

HAL的出現主要彌補了普通JSON格式在API交互中的不足,讓JSON更具有自描述性和導航性。同時,我們也注意到Web應用程序是將API組合起來為系統提供服務的開發模式。在組合API時,JSON在格式上缺乏描述性的缺陷就體現得非常明顯。我們要為API編寫文檔,要為API之間的數據關系和交互方式提供詳細的說明。而如果使用HAL+JSON來描述如代碼清單4-45所示的一個帶有location屬性的user信息,我們就可以很清晰地知道user信息和location信息的來源,這些信息都在子資源中有所體現。

代碼清單4-45 帶有location屬性的HAL+JSON風格請求和響應示例代碼

//請求
GET  http://api.example.com/users/tianyalan
//響應
Content-Type: application/json
{
    _links: {
        self: {
            href: "/users/tianyalan"
        }
    }
    "id": "user1",
    "name": "tianyalan",
    "email": "tianyalan@email.com"
    _embedded: {
        location: {
        _links: {
            self: {
                href: 'http:// api.locationservices.com/locations/1'
            }
        },
        id: 1,
        city: 'hangzhou'
        }
    }
}

講到這里,你可能會好奇,我們應該使用什么框架來開發類似這樣的Web API呢?Spring HATEOAS就是這樣一個功能強大的開發框架。事實上,Spring Boot框架內部也大量使用了Spring HATEOAS來對外暴露自解釋的Web API。這方面典型的案例就是提供系統監控功能的Spring Boot Actuator組件,我們在本書第12章中會有進一步介紹。

主站蜘蛛池模板: 苍梧县| 石阡县| 滁州市| 宁陵县| 浮山县| 绥阳县| 三江| 益阳市| 阳原县| 巧家县| 贵德县| 宁安市| 井研县| 沅江市| 衡南县| 平度市| 云安县| 威信县| 祁东县| 兰溪市| 凭祥市| 益阳市| 松江区| 阿荣旗| 潜山县| 昌图县| 河曲县| 盐津县| 邹城市| 荆门市| 永福县| 洮南市| 永济市| 如皋市| 类乌齐县| 蓬安县| 沛县| 云龙县| 汤原县| 双城市| 阆中市|