如何让Spring MVC + HATEOAS将资源列表编码为HAL?

时间:2015-01-25 18:25:39

标签: java spring spring-mvc spring-hateoas

我有一个春天HATEOAS ResourceModelResource 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?
  • 如何指定一致行为?

read about @EnableHypermediaSupport,但我的代码中没有设置它。

2 个答案:

答案 0 :(得分:8)

来自this GitHub issue

  

按预期工作。 HAL定义了必须的顶级资源   是一份文件。因此,根据定义,普通列表不能是HAL   文献。我们已将HAL自定义限制为仅应用   如果要呈现的根对象是ResourceSupport或子类型   它可以防止任意对象获得HAL自定义   应用。如果您创建ResourceSupport而不是List,则应该   看到正确呈现的HAL文档。

HAL Primer提供了更多详细信息以及此类顶级包装资源的示例。在Spring HATEOAS中,您使用Resources<T>来表示这样一个包装器,它本身是一个Resource<T>,其中包含self rel:

@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>扩展ResourceSupport就像Resource<T>一样。因此,您可以为ResourceAssembler创建Resources<ModelResource>,以避免必须手动创建self链接,并通常封装Resource<ModelResource>创建。


This answer表明,如果HAL渲染可用,它将由Spring Boot启用,这说明资源在可能的情况下呈现为HAL。

答案 1 :(得分:1)

我希望Spring自动选择application / hal + json作为所有ResponseEntity实例的默认Content-Type。