使用Spring RestTemplate和Super类型令牌消费Spring-hateoas Rest服务

Spring-hateoas为应用程序创建遵循HATEOAS原理的基于REST的服务提供了一种极好的方法。

我的目的不是要展示如何创建服务本身,而是要展示如何将客户端写入服务。

我将要使用的示例服务是Josh Long( @starbuxman )编写的“ the-spring-rest-stack ”。 我要使用的特定子项目是这里的阴影。 如果使用“ mvn jetty”命令运行此子项目,则可以在http:// localhost:8080 / users / 2中使用基于REST的端点列出用户的详细信息,其中“ 2”是用户的ID,并给出一个以下结构的结果:

{
    "links": [{
        "rel": "self",
        "href": "http://localhost:8080/users/2"
    }, {
        "rel": "customers",
        "href": "http://localhost:8080/users/2/customers"
    }, {
        "rel": "photo",
        "href": "http://localhost:8080/users/2/photo"
    }],
    "id": 2,
    "firstName": "Lois",
    "profilePhotoMediaType": null,
    "lastName": "Lane",
    "username": "loislane",
    "password": null,
    "profilePhotoImported": false,
    "enabled": true,
    "signupDate": 1370201631000
}

为了获得该用户的特定客户,端点位于http:// localhost:8080 / users / 2 / customers / 17,它提供以下结构的输出:

{
    "links": [{
        "rel": "self",
        "href": "http://localhost:8080/users/2/customers/17"
    }, {
        "rel": "user",
        "href": "http://localhost:8080/users/2"
    }],
    "id": 17,
    "signupDate": 1372461079000,
    "firstName": "Scott",
    "lastName": "Andrews",
    "databaseId": 17
}

现在,对于这两种服务的使用者而言,结果可以由Spring-hateoas项目中的一个称为Resource的Java类型表示,并且是具有以下签名的泛型类:

public class Resource<T> extends ResourceSupport {

 protected Resource() {
  this.content = null;
 }

 public Resource(T content, Link... links) {
  this(content, Arrays.asList(links));
 }

...

因此,以上两种服务的使用者将获得以下两种类型:

Resource<User> user = .... //call to the service

Resource<Customer> customer = ... //call to the service

现在的问题是,由于上面的“用户”和“客户”是参数化类型,如果我要使用杰克逊作为json处理器绑定这些类型,我将按照以下方式进行操作:

ObjectMapper objectMapper = new ObjectMapper();
Resource<Customer> customer = objectMapper.readValue(customerAsJson, Resource.class);
Resource<User> user = objectMapper.readValue(userAsJson, Resource.class);

上面的方法不起作用,原因是由于Java类型擦除导致参数化Resource的类型信息丢失,Jackson不知道创建Resource <User>或Resource <Customer>的实例

解决方法是使用超类型令牌 ,这实质上是一种提供像杰克逊库类型的信息和我以前的博客上讲述它在这里 。 这样,将json映射到适当的参数化类型的工作代码将如下所示:

ObjectMapper objectMapper = new ObjectMapper();
Resource<Customer> customer = objectMapper.readValue(customerAsJson, new TypeReference<Resource<Customer>>() {});
Resource<User> customer = objectMapper.readValue(userAsJson, new TypeReference<Resource<User>>() {});

Spring的基于Rest的服务的客户端抽象是RestTemplate ,它可以使用称为HttpMessageConverter的抽象处理各种消息格式(xml,json,atom等),以处理每种消息格式的绑定细节。

Spring RestTemplate提供了自己的Super Type令牌实现,能够按照Jackson的TypeReference的路线将不同的消息格式绑定到参数化类型,这被称为ParameterizedTypeReference

ParameterizedTypeReference可用于通过以下方式将用户和客户的Rest响应完全绑定到Java类型:

RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Resource<User>> responseEntity =
  restTemplate.exchange("http://localhost:8080/users/2", HttpMethod.GET, null, new ParameterizedTypeReference<Resource<User>>() {}, Collections.emptyMap());
if (responseEntity.getStatusCode() == HttpStatus.OK) {
 Resource<User> userResource = responseEntity.getBody();
 User user = userResource.getContent();
}
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Resource<Customer>> responseEntity =
  restTemplate.exchange("http://localhost:8080/users/2/customers/17", HttpMethod.GET, null, new ParameterizedTypeReference<Resource<Customer>>() {}, Collections.emptyMap());
if (responseEntity.getStatusCode() == HttpStatus.OK) {
 Resource<Customer> customerResource = responseEntity.getBody();
 Customer customer = customerResource.getContent();
}

总之,ParameterizedTypeReference提供了一种处理参数化类型的巧妙方法,并且在使用基于Spring Hateoas的REST服务时非常有用。


翻译自: https://www.javacodegeeks.com/2014/01/consuming-spring-hateoas-rest-service-using-spring-resttemplate-and-super-type-tokens.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值