根据Spring HATEOAS guide,资源列表的序列化方式是每个资源都显示其内容及其链接:
{
"content": [ {
"price": 499.00,
"description": "Apple tablet device",
"name": "iPad",
"links": [ {
"rel": "self",
"href": "http://localhost:8080/product/1"
} ],
"attributes": {
"connector": "socket"
}
}, {
"price": 49.00,
"description": "Dock for iPhone/iPad",
"name": "Dock",
"links": [ {
"rel": "self",
"href": "http://localhost:8080/product/3"
} ],
"attributes": {
"connector": "plug"
}
} ],
"links": [ {
"rel": "product.search",
"href": "http://localhost:8080/product/search"
} ]
}
如果是大型数据结构,我认为最好只提供资源的链接而不是像这样的资源本身(特别是在分页时):
{
"_links": {
"items": [{
"href": "http://localhost:8080/product/1"
},{
"href": "http://localhost:8080/product/3"
}]
}
}
除了这会减少传输字节的大小这一事实之外,HAL specification也提出了这一点。我目前正是这样做的
@RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity root(Pageable pageable, final PagedResourcesAssembler<Entity> assembler) {
Page<Entity> entities = entityRepository.findAll(pageable);
PagedResources<Resource> paged = assembler.toResource(entities,
EntityResourceAssembler.getInstance());
Collection<Resource> resources = paged.getContent();
ResourceSupport support = new ResourceSupport();
for (Resource r : resources) {
Link selfLink = r.getLink(Link.REL_SELF);
support.add(new Link(selfLink.getHref(), "items"));
}
return new ResponseEntity<ResourceSupport>(support, HttpStatus.OK);
}
但这有点难看,因为我&#34;手动&#34;需要从资源中获取自我链接。是否有更好/更聪明的方法来实现我想要的目标?
答案 0 :(得分:2)
我将忽略为什么你不想嵌入子资源(因此请求响应周期较少,客户端请求中更昂贵的部分)并尽可能地回答你的问题。
您无法使用内置PagedResourceAssembler
来执行您想要的操作。而是从ResourceSupport
派生一些东西,然后自己添加链接。我们在某些情况下执行此操作,我们只想链接而不是嵌入资源(因为资源不可用作HAL)
public class PageResource extends ResourceSupport {
@XmlAttribute(name = "page")
@JsonProperty("page")
private PageMeta pageMeta;
public PageResource() {
this.pageMeta = new PageMeta();
}
public PageMeta getPageMeta() {
return pageMeta;
}
public void setPageMeta(PageMeta pageMeta) {
this.pageMeta = pageMeta;
}
public static class PageMeta {
//Number of resources on this page.
@XmlAttribute @JsonProperty private long size;
//Total number of matching resources
@XmlAttribute @JsonProperty private long totalElements;
//Total number of page
@XmlAttribute @JsonProperty private long totalPages;
//Current page number
@XmlAttribute @JsonProperty private long number;
public PageMeta() {
}
public PageMeta(long size, long totalElements, long totalPages, long number) {
this.size = size;
this.totalElements = totalElements;
this.totalPages = totalPages;
this.number = number;
}
public long getSize() {
return size;
}
public void setSize(long size) {
this.size = size;
}
public long getTotalElements() {
return totalElements;
}
public void setTotalElements(long totalElements) {
this.totalElements = totalElements;
}
public long getTotalPages() {
return totalPages;
}
public void setTotalPages(long totalPages) {
this.totalPages = totalPages;
}
public long getNumber() {
return number;
}
public void setNumber(long number) {
this.number = number;
}
}
}
是一个非常简单的实现,然后在您的控制器中,您负责添加next和prev链接以及项链接。
此时,您可以构建自己的PagedResourceAssembler
,它只会执行链接,而不是嵌入子资源。
小一点......你应该考虑将链接添加为REL“item”而不是“items”。考虑链接集合并给json字段键赋予复数名称是很诱人的,但请记住HAL规范只使用字段键作为链接关系。
以html格式比较
<link rel="items" src="http://1"/>
<link rel="items" src="http://2"/>
到
<link rel="item" src="http://1"/>
<link rel="item" src="http://2"/>
很明显,每个链接的目标与集合共享一个项目关系,而不是“项目”,因为每个链接都是集合中的一个项目。