我有一个使用 Springboot Resttemplate 的 springboot 项目。我们已经从 1.5.3 迁移到 springboot 2.0.1,我们正试图通过使用 WebClient 使它的其余调用异步。我们曾经使用 Resttemplate 处理接收到的字符串,如下所示。但 WebClient 仅返回 Mono 或 Flux 中的数据。如何获取字符串形式的数据。已经尝试过 block() 方法,但它执行异步调用。
@Retryable(maxAttempts = 4, value = java.net.ConnectException.class,
backoff = @Backoff(delay = 3000, multiplier = 2))
public Mono<String> getResponse(String url) {
return webClient.get().uri(urlForCurrent).accept(APPLICATION_JSON)
.retrieve()
.bodyToMono(String.class);
}
使用 RestTemplate 呈现数据流
- 控制器接收客户端调用
- provider 获取 String 格式的数据
- 提供程序处理字符串
- 数据被提供给控制器
控制器.java
@RequestMapping(value = traffic/, method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
public String getTraffic(@RequestParam("place") String location) throws InterruptedException, ExecutionException {
String trafficJSON = Provider.getTrafficJSON(location)
return trafficJSON;
}
供应商.java
public String getTrafficJSON(String location) {
String url = ----;
ResponseEntity<String> response = dataFetcher.getResponse(url);
/// RESPONSEBODY IS READ AS STRING AND IT NEEDS TO BE PROCESSED
if (null != response {
return parser.transformJSON(response.getBody(), params);
}
return null;
}
DataFetcher.java
@Retryable(maxAttempts = 4,
value = java.net.ConnectException.class,
backoff = @Backoff(delay = 3000, multiplier = 2))
public ResponseEntity<String> getResponse(String url) {
/* ----------------------- */
return getRestTemplate().getForEntity(urlForCurrent, String.class);
}
原文由 Abhi 发布,翻译遵循 CC BY-SA 4.0 许可协议
由于存在很多误解,所以在这里我要澄清一些事情。
Spring 已经正式声明
RestTemplate
在maintenence mode
所以如果可以的话,使用WebClient
如果你想尽可能地证明未来。如 RestTemplate API 中所述
非反应性应用
如果您的应用程序是非反应性应用程序(不向调用客户端返回通量或单声道),您必须做的是使用
block()
如果您需要该值。您当然可以在您的应用程序内部使用Mono
或Flux
但最后您必须调用block()
返回具体的值–调用客户端。非反应性应用程序使用例如
tomcat
,undertow
作为底层服务器实现,它遵循 servlet 规范,因此它将为每个请求分配 1 个线程,因此您不会获得您获得的性能提升与一个反应性的应用程序。响应式应用
另一方面,如果你有一个反应性应用程序,你在任何情况下都不应该在你的应用程序中调用
block()
。阻塞正是它所说的,它会阻塞一个线程并阻止该线程执行直到它可以继续,这在反应世界中是不好的。您也不应该在您的应用程序中调用
subscribe
除非您的应用程序是响应的最终消费者。例如,如果您正在调用一个 api 来获取数据并写入您的应用程序连接到的数据库。您的后端应用程序是最终消费者。如果外部客户端正在调用您的后端(例如反应、角度应用程序、移动客户端等),则外部客户端是最终消费者,并且是订阅者。不是你。这里的底层默认服务器实现是一个
netty
服务器,它是一个非 servlet、基于事件的服务器, 不会 为每个请求分配一个线程,服务器本身是线程不可知的,任何可用的线程都可以随时处理任何事情在任何请求期间。webflux 文档 清楚地指出,servlet 3.1+ 支持的服务器 tomcat 和 jetty 都可以与 webflux 以及非 serlet 服务器 netty 和 undertow 一起使用。
我怎么知道我有什么应用程序?
Spring 声明,如果你同时拥有
spring-web
和spring-webflux
在类路径上,应用程序将支持spring-web
启动一个非默认应用程序雄猫服务器。如果需要作为弹簧状态,可以手动覆盖此行为。
“Spring WebFlux 框架”
那么如何按照题目提供的代码实现WebClient呢?
我会说这是最简单和最少侵入性的实现。您当然需要在
@Bean
中构建一个合适的网络客户端,并将其自动连接到它的类中。