由于存在很多误解,所以在这里我要澄清一些事情。
Spring官方表示RestTemplate
is in maintenence mode
所以如果可以的话,使用WebClient
如果您想尽可能面向未来。
如中所述RestTemplate API
NOTE:从 5.0 开始,此类处于维护模式,仅接受较小的更改请求和错误。请考虑使用org.springframework.web.reactive.client.WebClient
它具有更现代的 API,支持同步、异步和流场景。
非反应性应用
如果您的应用程序是非反应式应用程序(不向调用客户端返回通量或单声道),您需要做的是使用block()
如果你需要这个值。你当然可以使用Mono
or Flux
在您的应用程序内部,但最终您必须调用block()
获取需要返回给调用客户端的具体值。
非反应式应用程序使用例如tomcat
, undertow
作为底层服务器实现,它遵循 servlet 规范,因此它将为每个请求分配 1 个线程,因此您将无法获得响应式应用程序所获得的性能提升。
反应式应用程序
另一方面,如果您有一个反应式应用程序,则在任何情况下都不应该调用block()
在您的应用程序中。阻塞正如它所说的那样,它会阻塞一个线程并阻塞该线程的执行,直到它可以继续前进,这在反应式世界中是不好的。
你也不应该打电话subscribe
在你的申请中除非您的应用程序是响应的最终消费者。例如,如果您调用 api 来获取数据并将其写入应用程序连接到的数据库中。您的后端应用程序是最终的消费者。如果外部客户端正在调用您的后端(例如反应、角度应用程序、移动客户端等),则外部客户端是最终消费者,并且是订阅者。不是你。
这里的底层默认服务器实现是netty
服务器是一个非 servlet、基于事件的服务器,它将not为每个请求分配一个线程,服务器本身与线程无关,任何可用的线程都可以在任何请求期间随时处理任何事情。
The webflux 文档明确指出servlet 3.1+支持的服务器tomcat和jetty都可以与webflux以及非serlet服务器netty和undertow一起使用。
我怎么知道我有什么应用程序?
Spring 声明如果你两者都有spring-web
and spring-webflux
在类路径上,应用程序将倾向于spring-web
并默认启动一个带有底层 tomcat 服务器的非响应式应用程序。
如果需要作为弹簧状态,可以手动覆盖此行为。
两者都添加spring-boot-starter-web
and spring-boot-starter-webflux
应用程序中的模块会导致 Spring Boot 自动配置 Spring MVC,而不是 WebFlux。选择这种行为是因为许多 Spring 开发人员添加了spring-boot-starter-webflux
他们的 Spring MVC 应用程序使用反应式 WebClient。您仍然可以通过将所选应用程序类型设置为来强制执行您的选择SpringApplication.setWebApplicationType(WebApplicationType.REACTIVE)
.
“Spring WebFlux 框架”
那么如何按照问题提供的代码实现WebClient呢?
@Retryable(maxAttempts = 4,
value = java.net.ConnectException.class,
backoff = @Backoff(delay = 3000, multiplier = 2))
public Mono<String> getResponse(String url) {
return webClient.get()
.uri(url)
.exchange()
.flatMap(response -> response.toEntity(String.class));
}
我想说这是最简单且侵入性最小的实现。您当然需要构建一个合适的网络客户端@Bean
并将其自动装配到其类中。