Spring HATEOAS

一.簡(jiǎn)介

????????Spring HATEOAS的目標(biāo)是解決兩個(gè)問(wèn)題:link?creation(創(chuàng)建鏈接)及representation assembly(集合表述)。

二.創(chuàng)建鏈接

????????HATEOAS的核心是鏈接。鏈接的存在使得客戶(hù)端可以動(dòng)態(tài)發(fā)現(xiàn)其所能執(zhí)行的動(dòng)作。

HATEOAS生成鏈接的幾種方式:

① 靜態(tài)生成鏈接

????????Spring HATEOAS使用 org.springframework.hateoas.Link 類(lèi)來(lái)表示鏈接??梢岳^承自 Spring HATEOAS 提供的 org.springframework.hateoas.Resource 類(lèi),Resource 類(lèi)提供了簡(jiǎn)單的方式來(lái)創(chuàng)建鏈接。

Eg:

Link link1 = new Link("http://localhost:8080/something");

② 動(dòng)態(tài)生成鏈接

????????在創(chuàng)建資源的鏈接時(shí),指向單個(gè)資源的鏈接的href屬性值是類(lèi)似“http://localhost:8080/lists/1”這樣的格式。而其中的“/lists”不應(yīng)該是硬編碼的,否則當(dāng)修改了 ListRestController 類(lèi)的“@RequestMapping”時(shí),所有相關(guān)的生成鏈接的代碼都需要進(jìn)行修改。Spring HATEOAS 提供了 org.springframework.hateoas.mvc.ControllerLinkBuilder 來(lái)解決這個(gè)問(wèn)題,用來(lái)根據(jù) Spring MVC 控制器動(dòng)態(tài)生成鏈接。

Eg:

//通過(guò)slash方法找到下一級(jí),生成自身鏈接

Link link = linkTo(PersonController.class).slash(person.getId()).withSelfRel();

//如果實(shí)體類(lèi)實(shí)現(xiàn)Identifiable接口

Link link = linkTo(PersonController.class).slash(person).withSelfRel();

//通過(guò)指定類(lèi)的方法,生成rel為"items"的鏈接

Link link = linkTo(methodOn(ItemRestController.class).readItems(listId)).withRel("items");

③ 通過(guò)實(shí)體類(lèi)創(chuàng)建單個(gè)鏈接

????????首先需要添加Maven依賴(lài),此外還需要在控制器類(lèi)中通過(guò)“@ExposesResourceFor”注解聲明其所暴露的模型類(lèi),另外在 Spring 應(yīng)用的配置類(lèi)中需要通過(guò)“@EnableEntityLinks”注解來(lái)啟用 EntityLinks 功能。

Eg:

<dependency>

?<groupId>org.springframework.plugin</groupId>

?<artifactId>spring-plugin-core</artifactId>

?<version>1.1.0.RELEASE</version>

</dependency>


@RestController

@ExposesResourceFor(List.class)

@RequestMapping("/lists")

public class ListRestController {

@Autowired

private EntityLinks entityLinks;

entityLinks.linkForSingleResource(List.class, 1) ?

}

????????需要注意的是,為了linkForSingleResource方法可以正常工作,控制器類(lèi)中需要包含訪問(wèn)單個(gè)資源的方法,而且其“@RequestMapping”是類(lèi)似“/{id}”這樣的形式。

④Model—>ModelResource

????????繼承ResourceAssemblerSupport類(lèi),并根據(jù)ModelRestController與ModelResource進(jìn)行相應(yīng)配置。

//組裝單個(gè)資源對(duì)象

new ModelResourceAssembler().toResource(model);

//組裝資源對(duì)象的集合

Resources<ModelResource> resources = new Resources<ModelResource>(new ModelResourceAssembler().toResources(models));

二.集合表述

①Resource資源

????????繼承Resource類(lèi),在ModelResource類(lèi)中可以根據(jù)實(shí)體參數(shù)進(jìn)行自定義封裝,并向ModelResource中添加自定義鏈接。

Eg:

public class ChartResource extends Resource {????public ChartResource(Chart chart) throws Exception {????????super(chart);????????Long chartId = chart.getId();???????? add(linkTo(methodOn(ChartRestController.class).getDimensions(chartId)).withRel("dimensions"));//維度???????? add(linkTo(methodOn(ChartRestController.class).getConditions(1)).withRel("conditions"));//條件????}}

結(jié)果如下:

"id":?1,

"title":?"房?jī)r(jià)監(jiān)管",

"_links":?{

"dimensions":?{"href":?"http://localhost:8088/charts/1/dimensions"}, "conditions":?{"href":?"http://localhost:8088/charts/1/conditions"}, "self":?{"href":?"http://localhost:8088/charts/1"}

}

②_embedded子集合

????????首先是內(nèi)嵌資源在_embedded對(duì)應(yīng)的哈希對(duì)象中的屬性值,該屬性值是由 org.springframework.hateoas.RelProvider 接口的實(shí)現(xiàn)來(lái)提供的。對(duì)于應(yīng)用來(lái)說(shuō),只需要在內(nèi)嵌資源對(duì)應(yīng)的模型類(lèi)中添加 org.springframework.hateoas.core.Relation 注解即可.

@Relation(value = "list", collectionRelation = "lists")

public class List extends AbstractEntity {

}

CurieProvider API

????????使用URL作為鏈接的關(guān)系帶來(lái)的問(wèn)題是 URL 作為屬性名稱(chēng)來(lái)說(shuō)顯得過(guò)長(zhǎng),而且不同關(guān)系的 URL 的大部分內(nèi)容是重復(fù)的。為了解決這個(gè)問(wèn)題,可以使用 Curie。簡(jiǎn)單來(lái)說(shuō),Curie 可以作為鏈接關(guān)系 URL 的模板。鏈接的關(guān)系聲明時(shí)使用 Curie 的名稱(chēng)作為前綴,不用提供完整的 URL。應(yīng)用中聲明的 Curie 出現(xiàn)在_links 屬性中。

@Bean

public CurieProvider curieProvider() {

return new DefaultCurieProvider("todo",

new UriTemplate("http://www.midgetontoes.com/todolist/rels/{rel}"));

}

注意:CurieProvider每個(gè)應(yīng)用程序范圍只能定義一個(gè)bean

獲取鏈接屬性:

String?content =?"{'_links' : ?{ 'foo' : { 'href' : '/foo/bar' }}}";

LinkDiscoverer?discoverer =?new?HalLinkDiscoverer();

Link?link =?discoverer.findLinkWithRel("foo",?content);

assertThat(link.getRel(),?is("foo"));

assertThat(link.getHref(),?is("/foo/bar"));

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 這幾天在看Spirng-in-action-5,其中講Rest部分,著重提到了HATEOAS,描述了spring如...
    沉寂之舟閱讀 7,541評(píng)論 2 3
  • 原文鏈接:https://docs.spring.io/spring-boot/docs/1.4.x/refere...
    pseudo_niaonao閱讀 4,900評(píng)論 0 9
  • SpringMVC原理分析 Spring Boot學(xué)習(xí) 5、Hello World探究 1、POM文件 1、父項(xiàng)目...
    jack_jerry閱讀 1,487評(píng)論 0 1
  • http://liuxing.info/2017/06/30/Spring%20AMQP%E4%B8%AD%E6%...
    sherlock_6981閱讀 16,211評(píng)論 2 11
  • 每一次睡眠都是一次死亡,當(dāng)我們醒來(lái),便是全新的生命。 如此正好。 愿你,把每天當(dāng)做是末日來(lái)相愛(ài)。 不辜負(fù)、不孤獨(dú)、...
    文靜_明亞山分閱讀 265評(píng)論 0 0

友情鏈接更多精彩內(nèi)容