为啥 RestTemplate 不将响应表示绑定到 PagedResources?

Posted

技术标签:

【中文标题】为啥 RestTemplate 不将响应表示绑定到 PagedResources?【英文标题】:Why does RestTemplate not bind response representation to PagedResources?为什么 RestTemplate 不将响应表示绑定到 PagedResources? 【发布时间】:2014-06-07 23:26:13 【问题描述】:

我正在使用 spring-data-rest 将实体公开为(分页)休息资源。一切正常,但是当我通过RestTemplate 请求数据时,我得到了一个无用的 HATEOAS JSON(我没有要求)。 JSON 似乎是 PagedResources。我可以忍受,但 JSON 没有正确转换为对象。里面没有content

存储库:

@RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends PagingAndSortingRepository<Person, Long>

    List<Person> findByLastName(@Param("name") String name);

客户:

public List<Person> getPersons()

    RestTemplate rt = new RestTemplate();
    System.out.println(rt.getForObject(URL, PagedResources.class).getContent().size());
    System.out.println(rt.getForObject(URL, PagedResources.class).getLinks().size());
    System.out.println(rt.getForObject(URL, PagedResources.class).getMetadata().getTotalElements());
    return new ArrayList<Person>(rt.getForObject(URL, PagedResources.class).getContent()); // <-- empty

系统输出:

0 // getContent().size()
4 // getLinks().size()
2 // getTotalElements()

卷曲:

C:\...>curl http://localhost:8080/spring-jsf-rest/rest/people

  "_links" : 
    "self" : 
      "href" : "http://localhost:8080/spring-jsf-rest/rest/people?page,size,sort",
      "templated" : true
    ,
    "search" : 
      "href" : "http://localhost:8080/spring-jsf-rest/rest/people/search"
    
  ,
  "_embedded" : 
    "people" : [ 
      "firstName" : "John",
      "lastName" : "Rambo",
      "_links" : 
        "self" : 
          "href" : "http://localhost:8080/spring-jsf-rest/rest/people/1"
        
      
    , 
      "firstName" : "Chuck",
      "lastName" : "Norris",
      "_links" : 
        "self" : 
          "href" : "http://localhost:8080/spring-jsf-rest/rest/people/2"
        
      
     ]
  ,
  "page" : 
    "size" : 20,
    "totalElements" : 2,
    "totalPages" : 1,
    "number" : 0
  

_embedded 似乎没有正确映射到内容?!

【问题讨论】:

展望未来,您可能想重新考虑在这里提问的方式。如果东西对你没用,就不要使用它。请不要声称,如果您明确发出GET 请求,您就没有要求。与计算机一样,您完全得到您所要求的。如果您不指定 Accept 标头,您将获得默认值,即 application/hal+json。一般来说,这种消极的语气不会产生回答的动力。尽管如此,我还是抓紧时间。不客气。 PS:什么是 HATEOAS JSON,顺便说一句? @Oliver:我承认,我的语气有点消极。但是那些小障碍会很烦人。当然,我尝试了其他接受标头,但结果始终相同。我不是唯一一个遇到这个问题的人:***.com/q/23264044/3563584。我也没有选择使用东西,我必须这样做。 Ahhhh 这就是您在客户端解析 _embedded 列表的方式,告诉 RestTemplate 期待其中一个 hatoas 资源类。非常有用,spring-data-rest 文档在客户端相当稀疏 【参考方案1】:

正如您正确发现的那样,PagedResources 没有 _embedded 属性,这就是您没有填充 content 属性的原因。

这个困境可以通过两种不同的方式解决:

    首先提供与表示匹配的类型。因此,制作一个自定义类并坚持使用表示的属性名称或使用 Jackson 注释等对其进行自定义。

    设置自定义 MappingJackson2HttpMessageConverter 并自定义 ObjectMapper 以配置 Spring HATEOAS 开箱即用的 Jackson2HalModule

    ObjectMapper mapper = new ObjectMapper();
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    mapper.registerModule(new Jackson2HalModule());
    
    MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
    converter.setSupportedMediaTypes(MediaType.parseMediaTypes("application/hal+json"));
    converter.setObjectMapper(mapper);
    
    RestTemplate template = new RestTemplate(Collections.<HttpMessageConverter<?>> singletonList(converter));
    

【讨论】:

非常感谢您的帮助。选项 2 看起来不错。但我得到“无法识别的字段“模板化”(类 org.springframework.hateoas.Link),未标记为可忽略(一个已知属性:“href”])”。我想我必须深入挖掘。如果我不能让它工作,我想我会坚持选项 1。 我认为您可以通过设置objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 来摆脱这种情况。默认情况下,杰克逊非常严格。相应地更新了答案。 嗯,如果我这样做things break for me - 有什么想法吗? @OliverDrotbohm 我也有同样的问题,不同的是我没有使用 RestTemplate,而是使用 FeignClient。我能做什么?

以上是关于为啥 RestTemplate 不将响应表示绑定到 PagedResources?的主要内容,如果未能解决你的问题,请参考以下文章

为啥不将 Javascript 事件委托发挥到极致呢?

WebClient 与 RestTemplate

为啥 execlp() 不将输出打印到终端?

RxSwift 不将数据绑定到自定义集合视图单元格

为啥不将值添加到 NSMutableArray?

将RestTemplate响应映射到java Object