我有一个春季 HATEOAS Resource
,这样ModelResource extends Resource<Model>
.
在@RestController
我有一种方法可以创建新Model
:
@RequestMapping(value = "", method = POST)
public ResponseEntity<ModelResource> postModel() {
Model model = service.create().model;
ModelResource resource = assembler.toResource(model);
HttpHeaders headers = new HttpHeaders();
headers.setLocation(URI.create(resource.getLink("self").getHref()));
return new ResponseEntity<>(resource, headers, CREATED);
}
从上述方法返回的创建ModelResource
是 HAL 编码的:
$ curl -v -XPOST localhost:8080/models
> POST /models HTTP/1.1
> User-Agent: curl/7.32.0
> Host: localhost:8080
> Accept: */*
>
< HTTP/1.1 201 Created
< Date: Sun, 25 Jan 2015 11:51:50 GMT
< Location: http://localhost:8080/models/0
< Content-Type: application/hal+json; charset=UTF-8
< Transfer-Encoding: chunked
< Server: Jetty(9.2.4.v20141103)
<
{
"id" : 0,
"_links" : {
"self" : {
"href" : "http://localhost:8080/models/0"
}
}
}
在同一控制器中也有列出Model
的方法。
@RequestMapping(value = "", method = GET)
public List<ModelResource> getModels() {
return service.find().stream()
.map(modelProxy -> assembler.toResource(modelProxy.model))
.collect(Collectors.toList());
}
出于某种原因,此方法返回纯 JSON,而不是 HAL:
$ curl -v localhost:8080/models
> GET /models HTTP/1.1
> User-Agent: curl/7.32.0
> Host: localhost:8080
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Sun, 25 Jan 2015 11:52:00 GMT
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Server: Jetty(9.2.4.v20141103)
<
[ {
"id" : 0,
"links" : [ {
"rel" : "self",
"href" : "http://localhost:8080/models/0"
} ]
} ]
- 为什么第一种方法返回 HAL,而第二种方法返回纯 JSON?
- 如何指定一致的行为?
我已经阅读了有关@EnableHypermediaSupport
的信息,但我没有在我的代码中的任何位置设置它。
来自这个 GitHub 问题:
这按预期工作。HAL 定义了必须 是文档。因此,根据定义,纯列表不能是 HAL。 公文。我们已将 HAL 自定义限制为仅应用 如果要呈现的根对象是资源支持或子类型 它以防止任意对象获得 HAL 自定义 应用的。如果创建资源支持而不是列表,则应 请参阅呈现正确的 HAL 文档。
HAL 入门提供了有关此类顶级包装资源外观的更多详细信息和示例。在Spring HATEOAS中,你使用Resources<T>
来表示这样一个包装器,它本身是一个带有self
rel的Resource<T>
:
@RequestMapping(value = "", method = GET)
public Resources<ModelResource> getModels() {
List<ModelResource> models = service.find().stream()
.map(modelVertex -> assembler.toResource(modelVertex.model))
.collect(Collectors.toList());
return new Resources<>(models, linkTo(methodOn(ModelController.class).getModels()).withRel("self"));
}
然后将返回的Resources<T>
类型编码到包含嵌入文档的文档:
$ curl -v localhost:8080/models
> GET /models HTTP/1.1
> User-Agent: curl/7.32.0
> Host: localhost:8080
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Sun, 25 Jan 2015 13:53:47 GMT
< Content-Type: application/hal+json; charset=UTF-8
< Transfer-Encoding: chunked
< Server: Jetty(9.2.4.v20141103)
<
{
"_links" : {
"self" : {
"href" : "http://localhost:8080/models"
}
},
"_embedded" : {
"modelList" : [ {
"id" : 0,
"_links" : {
"self" : {
"href" : "http://localhost:8080/models/0"
},
"links" : {
"href" : "http://localhost:8080/models/0/links"
}
}
} ]
}
}
如上所述,Resources<T>
像Resource<T>
一样扩展ResourceSupport
。因此,您可以为Resources<ModelResource>
创建一个ResourceAssembler
,以避免手动创建self
链接,并通常封装Resource<ModelResource>
创建。
这个答案表明 HAL 渲染是由 Spring 引导启用的(如果可用),这解释了资源在可能的情况下被渲染为 HAL。
我希望Spring会自动选择application/hal+json作为所有ResponseEntity实例的默认内容类型。