一.簡介
????????Spring HATEOAS的目標是解決兩個問題:link?creation(創(chuàng)建鏈接)及representation assembly(集合表述)。
二.創(chuàng)建鏈接
????????HATEOAS的核心是鏈接。鏈接的存在使得客戶端可以動態(tài)發(fā)現(xiàn)其所能執(zhí)行的動作秋茫。
HATEOAS生成鏈接的幾種方式:
① 靜態(tài)生成鏈接
????????Spring HATEOAS使用 org.springframework.hateoas.Link 類來表示鏈接法褥∪枋浚可以繼承自 Spring HATEOAS 提供的 org.springframework.hateoas.Resource 類抵乓,Resource 類提供了簡單的方式來創(chuàng)建鏈接。
Eg:
Link link1 = new Link("http://localhost:8080/something");
② 動態(tài)生成鏈接
????????在創(chuàng)建資源的鏈接時阎抒,指向單個資源的鏈接的href屬性值是類似“http://localhost:8080/lists/1”這樣的格式。而其中的“/lists”不應該是硬編碼的消痛,否則當修改了 ListRestController 類的“@RequestMapping”時且叁,所有相關的生成鏈接的代碼都需要進行修改。Spring HATEOAS 提供了 org.springframework.hateoas.mvc.ControllerLinkBuilder 來解決這個問題秩伞,用來根據(jù) Spring MVC 控制器動態(tài)生成鏈接逞带。
Eg:
//通過slash方法找到下一級欺矫,生成自身鏈接
Link link = linkTo(PersonController.class).slash(person.getId()).withSelfRel();
//如果實體類實現(xiàn)Identifiable接口
Link link = linkTo(PersonController.class).slash(person).withSelfRel();
//通過指定類的方法,生成rel為"items"的鏈接
Link link = linkTo(methodOn(ItemRestController.class).readItems(listId)).withRel("items");
③ 通過實體類創(chuàng)建單個鏈接
????????首先需要添加Maven依賴掰担,此外還需要在控制器類中通過“@ExposesResourceFor”注解聲明其所暴露的模型類汇陆,另外在 Spring 應用的配置類中需要通過“@EnableEntityLinks”注解來啟用 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方法可以正常工作毡代,控制器類中需要包含訪問單個資源的方法,而且其“@RequestMapping”是類似“/{id}”這樣的形式勺疼。
④Model—>ModelResource
????????繼承ResourceAssemblerSupport類教寂,并根據(jù)ModelRestController與ModelResource進行相應配置。
//組裝單個資源對象
new ModelResourceAssembler().toResource(model);
//組裝資源對象的集合
Resources<ModelResource> resources = new Resources<ModelResource>(new ModelResourceAssembler().toResources(models));
二.集合表述
①Resource資源
????????繼承Resource類执庐,在ModelResource類中可以根據(jù)實體參數(shù)進行自定義封裝酪耕,并向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":?"房價監(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對應的哈希對象中的屬性值轨淌,該屬性值是由 org.springframework.hateoas.RelProvider 接口的實現(xiàn)來提供的迂烁。對于應用來說,只需要在內(nèi)嵌資源對應的模型類中添加 org.springframework.hateoas.core.Relation 注解即可.
@Relation(value = "list", collectionRelation = "lists")
public class List extends AbstractEntity {
}
③ CurieProvider API
????????使用URL作為鏈接的關系帶來的問題是 URL 作為屬性名稱來說顯得過長递鹉,而且不同關系的 URL 的大部分內(nèi)容是重復的盟步。為了解決這個問題,可以使用 Curie躏结。簡單來說却盘,Curie 可以作為鏈接關系 URL 的模板。鏈接的關系聲明時使用 Curie 的名稱作為前綴媳拴,不用提供完整的 URL黄橘。應用中聲明的 Curie 出現(xiàn)在_links 屬性中。
@Bean
public CurieProvider curieProvider() {
return new DefaultCurieProvider("todo",
new UriTemplate("http://www.midgetontoes.com/todolist/rels/{rel}"));
}
注意:CurieProvider每個應用程序范圍只能定義一個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"));