java webclient 下载_Java: Spring WebClient 和 RestTemplate

0. 简述

此文将简要介绍Spring 中的两种 web client 实现 - RestTemplate 和 WebClient

并说明两者的差异

1. RestTemplate 阻塞型客户端

Spring 很早就提供了 RestTemplate 作为 web 客户端的抽象。在底层,RestTemplate 使用了基于每个请求对应一个线程模型(thread-per-request model)的 Java Servlet API

这意味着客户端线程在收到服务器响应之前,将一直被阻塞。当访问大量响应速度较慢的服务时,数量众多的阻塞线程将占用大量的服务器资源,严重影响性能。

2. WebClient 非阻塞型客户端

为了解决上述问题 ,在 Spring 5 中引入了 WebClient ,使用了 Spring Reactive 框架提供的异步、非阻塞解决方案。

Spring Reactive 框架 使用事件驱动模型,通过 Streams API 提供了组合异步逻辑的方法。与同步/阻塞方法相比,它可以使用更少的线程和系统资源来处理更多的业务逻辑。

与 RestTemplate 为每一个事件都新建一个线程不同, WebClient 为每一个事件创建一个“任务”,Spring Reactive 框架 将对这些“任务”进行队列处理,仅在收到适当的响应时才执行任务。

3 . 准备

Maven 依赖

org.springframework.boot

spring-boot-starter-webflux

我们先创建一个响应时间较慢的服务

@GetMapping("/slow-service-tweets")

private List getAllTweets() {

Thread.sleep(2000L); // 延迟两秒 return Arrays.asList(

new Tweet("RestTemplate rules", "@user1"),

new Tweet("WebClient is better", "@user2"),

new Tweet("OK, both are useful", "@user1"));

}

4. 使用 RestTemplate 调用慢服务

@GetMapping("/tweets-blocking")

public List getTweetsBlocking() {

log.info("Starting BLOCKING Controller!");

final String uri = getSlowServiceUri();

RestTemplate restTemplate = new RestTemplate();

ResponseEntity> response = restTemplate.exchange(

uri, HttpMethod.GET, null,

new ParameterizedTypeReference>(){});

List result = response.getBody();

result.forEach(tweet -> log.info(tweet.toString()));

log.info("Exiting BLOCKING Controller!");

return result;

}

当我们调用这个endpoint时,由于RestTemplate的同步特性,代码将阻塞以等待来自慢服务的响应。只有在接收到响应时,才会执行此方法中的其余代码。在日志中,我们可以看到:

Starting BLOCKING Controller!

Tweet(text=RestTemplate rules, username=@user1)

Tweet(text=WebClient is better, username=@user2)

Tweet(text=OK, both are useful, username=@user1)

Exiting BLOCKING Controller!

5. 使用 WebClient 调用慢速服务

@GetMapping(value = "/tweets-non-blocking",

produces = MediaType.TEXT_EVENT_STREAM_VALUE)

public Flux getTweetsNonBlocking() {

log.info("Starting NON-BLOCKING Controller!");

Flux tweetFlux = WebClient.create()

.get()

.uri(getSlowServiceUri())

.retrieve()

.bodyToFlux(Tweet.class);

tweetFlux.subscribe(tweet -> log.info(tweet.toString()));

log.info("Exiting NON-BLOCKING Controller!");

return tweetFlux;

}

在这个例子中,WebClient 返回一个 Flux publisher 然后gets()方法执行完毕。代码继续执行,当结果可用时,publisher 将会打印返回的数据。

执行结果:

Starting NON-BLOCKING Controller!

Exiting NON-BLOCKING Controller!

Tweet(text=RestTemplate rules, username=@user1)

Tweet(text=WebClient is better, username=@user2)

Tweet(text=OK, both are useful, username=@user1)

我们注意到,此方法在接收到响应之前已经完成。

6. 总结

RestTemplate 使用 Java Servlet API,是同步和阻塞的方法。

WebClient 是异步的,在等待响应返回时不会阻塞正在执行的线程。只有当响应就绪时,才会产生通知。

在某些情况下,非阻塞方法使用的系统资源要少得多。因此,在这些情况下,WebClient 将是更好的选择。

本文中提到的所有代码,可以点此下载 Github

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值