spring - 在 Spring Rest Data (HATEOAS) 中使用 RestTemplate 创建对象之间的关联

标签 spring resttemplate spring-data-rest spring-hateoas

我正在努力通过 RestTemplate 在 Spring Data Rest API 上操作对象(它们是 JPA 实体)。

我有一个树结构,其中流派有其他流派的 parent 和 child (它是 itunes genre tree )

创建一个对象很好:

URI selfLink = restTemplate.postForLocation(api+"/genre", genre, Collections.emptyMap());

与之建立关联并不是那么容易。如果我尝试像这样放置一个父关联:
headers.setContentType(new MediaType("text", "uri-list"));
...
restTemplate.put(selfLink.toString()+"/parent", entity, parentGenreURI );

我在客户端收到 500 Internal Server 错误,但实际错误在 REST API 端被吞下,并且日志中没有任何内容。

如果我尝试使用父级的 uri 修补 URI 本身,如下所示:
headers.setContentType(MediaType.APPLICATION_JSON);
...
Map map = ImmutableMap.of("parent", parentGenreLink);
restTemplate.exchange(selfLink.toString()+"/parent", HttpMethod.PATCH, entity, String.class, map);

我在客户端收到 400 Bad Request 错误,在服务器上收到

org.springframework.http.converter.HttpMessageNotReadableException: Could not read an object of type class Genre from the request!; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: Could not read payload!; nested exception is com.fasterxml.jackson.databind.JsonMappingException: No content to map due to end-of-input



这让我认为这是正确的做法,但我只是做错了。

任何人都可以提供一些指导吗?我看到的每个示例都只使用 curl,这对我没有太大帮助:)

关于 SO 有一些类似回答的问题,但其中大多数要么指向不再存在的文档,要么具有如此简单的对象,所有内容都被转储到 map 中。

最佳答案

查看您发布的少量代码和您收到的错误,我认为您以错误的方式调用您的服务。

我在这里以第二次通话为例,但是由于我认为您在两次通话中都犯了同样的错误,因此第一个错误的解决方案应该是类似的。

如果我们查看 RestTemplate.exchange 的文档你打电话我们可以看到它需要以下参数:

  • 调用
  • 的网址
  • 使用方法
  • 作为请求发送的 HttpEntity
  • 响应的类别
  • URL中要替换的参数值

  • 我认为您出错的地方是参数 3 和 5。在我看来,您正在尝试发送 JSON 有效负载
    {
      "parent": "someGenre"
    }
    

    但是您实际上在做的是告诉模板用 parentGenreLink 的值替换 URL 中出现的任何字符串 {parent}(一个 URL 参数占位符)。

    您可能想要做的是将 map 设置为 HttpEntity 上的主体,而不是传递任何 URL 参数:
    // Create the body
    Map map = ImmutableMap.of("parent", parentGenreLink);
    
    // Create the headers
    Headers headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    
    // Create the HTTP Entity
    HttpEntity<?> entity = new HttpEntity<>(map, headers);
    
    // Make the call without any URL parameters
    restTemplate.exchange(selfLink.toString()+"/parent", HttpMethod.PATCH, entity, String.class);
    

    请注意,要使其正常工作,您必须在模板上设置一个能够(反)序列化 JSON 的消息转换器:
    RestTemplate restTemplate = new RestTemplate();
    
    List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
    messageConverters.add(new MappingJacksonHttpMessageConverter());
    restTemplate.setMessageConverters(messageConverters);
    

    关于spring - 在 Spring Rest Data (HATEOAS) 中使用 RestTemplate 创建对象之间的关联,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31702707/

    相关文章:

    java - 如何使用 Spring reactive 通过增量进度更新逐一处理每个产品?

    java - 休息模板 - 没有可用的缓冲区空间(已达到最大连接数?)

    java - 一次完成基本身份验证

    Spring Data Rest - 更改项目资源 url 中使用的实体属性

    java - 如果我们在 spring MVC 中互换 @service 和 @repository 注解会发生什么

    Spring Data Redis - UUID id - ConverterNotFoundException

    java - 使用 @Component 给出属性名称/值

    android - 通过 RestTemplate 发送多部分文件

    java - Spring Data REST - 如何在投影中包含计算数据?

    java - Spring Data Rest - Bean 验证未应用于 PUT 方法?