【问题标题】:Consuming HAL-based REST service with spring-hateoas使用 spring-hateoas 使用基于 HAL 的 REST 服务
【发布时间】:2017-08-16 01:55:03
【问题描述】:

我正在尝试使用带有 RestTemplate 类的基于 HAL 的 REST 服务。 响应正文如下所示:

{
  "_embedded": {
    "school:teachers": [
      {
        "name": "Adams",
        "state": "CA",
        "_links": {
          "self": {
            "href": "http://localhost:8080/api/teachers/1"
          }
        }
      },
      {
        "name": "Barnes",
        "state": "FL",
        "_links": {
          "self": {
            "href": "http://localhost:8080/api/teachers/2"
          }
        }
      },
      {
        "name": "Armstrong",
        "state": "GA",
        "_links": {
          "self": {
            "href": "http://localhost:8080/api/teachers/3"
          }
        }
      }
    ]
  },
  "_links": {
    "curies": [
      {
        "href": "http://localhost:8080/docs/html5/{rel}.html",
        "name": "school",
        "templated": true
      }
    ]
  }
}

Teacher 类如下所示:

public class Teacher {
    private String name;
    private String state;

    // getters and setters...
}

GET方法的REST服务返回类型为ResponseEntity<Resources<Resource<Component>>>。因此,我在客户端代码中的请求如下所示:

...
RestTemplate restTemplate = new RestTemplate();

Map<String, Object> dummy = new HashMap<>();
HttpEntity<String> httpEntity = getHttpEntity(); 

ResponseEntity<Resources<Resource<Teacher>>> response = restTemplate.exchange(url,
                HttpMethod.GET,
                httpEntity,
                new ParameterizedTypeReference<Resources<Resource<Teacher>>>() {});

Resources<Resource<Teacher>> resources = response.getBody();
...

当我使用响应类型ParameterizedTypeReference 发出请求时,响应的内容为空。当我使用String 进行操作时,我会检索内容列表。

我应该如何使用响应类型ParameterizedTypeReference 进行检索以将其直接映射到 POJO 中?

【问题讨论】:

  • 您返回Resources&lt;Resource&lt;Teacher&gt;&gt; 的服务似乎非常值得怀疑。如果您控制代码,请考虑更改它。也就是说,您必须在客户端使用RestTemplate 吗?如果没有,Traverson 是一个更好的选择,因为它是为导航 HAL 响应而构建的,而 RestTemplate 不是。
  • @AbhijitSarkar 我不控制服务器端代码,因此我必须使用它。我从没听说过 Traverson,我得看看如何提出请求。
  • @AbhijitSarkar Resources&lt;Resource&lt;Teacher&gt;&gt; 有什么问题?
  • @AbhijitSarkar 必须问同样的问题 - 该响应类型有什么问题?这既合法又普遍。特别是为什么你认为这很重要。问题是关于消费 JSON,确定吗?所以服务器上的响应“类型”是无关紧要的。

标签: java spring rest spring-hateoas


【解决方案1】:

当然,你应该选择 Traverson

Traverson client = new Traverson(new URI("http://localhost:8080/api/"), 
         MediaTypes.HAL_JSON);
    Resources<Resource<Teacher>> teachers = client
        .follow("school:teachers")
        .toObject(new ResourcesType<Resource<Teacher>>(){});

https://docs.spring.io/spring-hateoas/docs/current/reference/html/#client.traverson

【讨论】:

    【解决方案2】:

    我尝试了与 Vishnoo Rath 类似的方法。我计划为我的所有资源构建一个通用方法。

    ResponseEntity<String> response = 
                    restTemplate.exchange("http://localhost:8081/rest/cars", HttpMethod.GET, null, String.class);
    
            String data = response.getBody();
            //log.info(data);
    
            ObjectMapper om = new ObjectMapper();
            om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    
            JsonNode jsNode = om.readTree(data);
            String test = jsNode.at("/_embedded/cars").toString();
            //log.info(test);
    
            ArrayList<Car> cars = om.readValue(test, new TypeReference<List<Car>>() {
            });
    
            for (Car theCar : cars) {
                log.info(">>> " + theCar.getMake() + " " + theCar.getModel() + " " + theCar.getYear());
            }
    

    【讨论】:

      【解决方案3】:

      我在JAVA中使用Bowman消费JSON+HAL资源。与this article 所示的 RestTemplate 相比,该库极大地简化了资源的消耗。

      【讨论】:

      • 不要链接到外部网址,请在答案中添加相关代码和解释。
      【解决方案4】:

      我也遇到了类似的问题。我选择解决它的方式是:

              ResponseEntity<String> response = restTemplate.exchange(
                      "http://localhost:8080/payment/search/findByApprovalDate?approvalDate=2017-11-06", HttpMethod.GET,
                      null, String.class);
      
              String data = response.getBody();
      
              ObjectMapper om = new ObjectMapper();
              om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
      
              JsonNode jsNode = om.readTree(data);
              String test = jsNode.at("/_embedded/payment").toString();
      
              payments = om.readValue(test, new TypeReference<List<RHPayment>>() {
              });
      

      【讨论】:

        猜你喜欢
        • 2016-06-13
        • 1970-01-01
        • 1970-01-01
        • 2017-03-14
        • 2019-03-23
        • 2015-03-03
        • 2018-07-23
        • 1970-01-01
        • 2017-12-10
        相关资源
        最近更新 更多