消费REST

Spring应用除了提供对外API之外,也可以对另外一个应用的API发送请求。

使用 RestTemplate消费REST端点

从Spring Framework 5开始,除了WebFlux之外,Spring还引入了一个名为WebClient的新HTTP客户端。WebClient是RestTemplate的现代替代HTTP客户端。它不仅提供传统的同步 API,还支持高效的非阻塞和异步方法。也就是说,如果我们正在开发新应用程序或迁移旧应用程序,那么使用WebClient是一个好主意。展望未来,RestTemplate 将在将来的版本中弃用。

Rest提供了与REST资源交互的方法。

RestTemplate中12个独立的操作

方法描述
delete()在特定的URL上对资源执行HTTP DELETE操作
exchange()在URL上执行特定的HTTP方法,返回包含对象的ResponseEntity,这个对象是从响应体中映射的得到的
execute()在URL上执行特定的HTTP方法,返回一个从响应体映射得到的对象
getForEntity()发送一个HTTP GET请求,返回的ResponseEntity包含了响应体所映射成的对象
getForObject()发送一个HTTP GET请求,返回的请求体将映射为一个对象
headForHeaders()发送HTTP HEAD请求,返回包含特定资源URL的HTTP头信息
optionsForAllow()发送HTTP OPTIONS请求,返回特定URL的Allow头信息
patchForObject()发送HTTP PATCH请求,返回一个从响应体映射得到的对象
postForEntity()POST数据到一个URL,返回包含一个对象的ResponseEntity,这个对象是从响应体中映射得到的
postForLocation()POST数据到一个URL,返回新创建资源的URL
postForObject()POST数据到一个URL,返回根据响应体匹配形成的对象
put()PUT资源到特定的URL

上述大多数操作都以三种方法的形式进行了重载。

  • 使用String 作为URL格式,并使用可变参数列表指明URL参数。
  • 使用String作为URL格式,并使用Map<String ,String>指明URL参数
  • 使用Java.net.URL作为URL格式,不支持参数化URL

要使用RestTemplate,可以在需要的地方创建实例,也可以声明为一个bean主要到需要的地方

RestTemplate restTemplate = new RestTemplate();
@Bean
public RestTamplate restTemplate() {
    return new RestTemplate() ;
}

GET资源

@SpringBootApplication
public class SpringBootDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootDemoApplication.class, args);

        RestTemplate restTemplate = new RestTemplate();
        Ingredient ingredient = restTemplate.getForObject("http://localhost:8080/test",Ingredient.class);
        System.out.println(ingredient);
    }

}

可变参数Id

Ingredient ingredient = restTemplate.getForObject("http://localhost:8080/ingredients/{id}",Ingredient.class,ingredientId);


Map指定URL变量

public Ingredient get(String Id) {
    Map<String,String> urlVariables = new HashMap<>;
    urlVariables.put("id",Id);
    return restTempalate.getForObject("http://localhost:8080/ingredients/{id}",Ingredient.class,urlVariables);
}

使用URL参数要稍微复杂一点,这种方式需要我们在调用getForObject之前构建一个URL对象。

public Ingredient get(String Id) {
    Map<String,String> urlVariables = new HashMap<>;
    urlVariables.put("id",Id);
    URL url = UriComponentsBuider
        .fromHttpUrl("http://localhost:8080/ingredients/{id}")
        .build(urlVariables);
    return restTempalate.getForObject(url,Ingredient.class);
}

其他put,delete,post方法与上述get方法非常相似。

使用Traverson导航REST API

Traverson来源于Spring Data HATEOAS项目,是Spring应用中开箱即用的消费超媒体API的解决方案。

Traverson traverson = new Traverson(
                URI.create("http://localhost:8080/api"), MediaTypes.HAL_JSON);
        ParameterizedTypeReference<CollectionModel<Ingredient>> ingredientType =
                new ParameterizedTypeReference<CollectionModel<Ingredient>>() {};

        CollectionModel<Ingredient> ingredientRes =
                traverson.follow("ingredients").toObject(ingredientType);
        System.out.println(ingredientRes)

记住重点是MediaTypes.HAL_JSON

要使用Traverson,首先我们要用基础URL实例化一个Traverson对象,在这里我们将URL指向了基础URL。从这里开始我们就可以根据链接的关系名来遍历API、我们同时还指定了API会生成JSON格式的响应,并且具有HAL风格的超链接,这样Traverson就知道怎么解析传入的数据了。与RestTemplate相似,可以实例化也可声明为Bean使用。

通过follow方法我们可以导航至链接关系名为ingredients的资源。我们需要调用toObject来提取资源的内容。

我们需要告诉toObject方法要将数据读取到哪种对象之中,考虑到我们需要以CollectionModel对象的形式读入,而且Java类型擦除使得为泛型提供类型信息变得非常困难,但是,我们通过创建 ParameterizedTypeReference能够解决这个问题。

我们可以轻松跟踪taco链接,找到我们想要的内容。所以基于ParameterizedTypeReference调用toObject方法,我们就得到了我们想要的内容。

ParameterizeTypeReference<CollectionModel<Taco>> tacoType = 
    new ParameterizedTypeReference<CollectionModel<Taco>>() {};
​
CollectionModel<Taco> tacoRes = 
    traverson.follow("tacos").follow("recents").toObject(tacoType);
​
Collection<Taco> tacos = tacoRes.getContent();

我们可以通过列出关系名称来简化follow方法:

Collection<Taco> tacoRes =
    traverson.follow("tacos", "recents").toObject(tacoType);

结合

Traverson 可以轻松地引导启用了 HATEOAS 的 API 并调用其资源。但有一件事它没有提供任何方法来编写或删除这些 API。相比之下,RestTemplate 可以编写和删除资源,但不便于引导 API。
当需要同时引导 API 和更新或删除资源时,需要同时使用 RestTemplate 和 Traverson。Traverson 仍然可以用于引导到将创建新资源的链接。然后可以给 RestTemplate 一个链接来执行 POST、PUT、DELETE 或任何其他 HTTP 请求。

private Ingredient addIngredient(Ingredient ingredient) {
    String ingredientsUrl = traverson.follow("ingredients")
        .asLink().getHref();
    
    return rest.postForObject(ingredientsUrl,
                             ingredient,
                             Ingredient.class);
}

在 follow Ingredient 链接之后,通过调用 asLink() 得到链接本身。在该链接中,通过调用 getHref() 得到链接的 URL。有了 URL,就有了在 RestTemplate 实例上调用 postForObject() 并保存新 Ingredient 所需的一切。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值