Abh*_*bhi 9 java spring spring-boot spring-webflux
我有一个使用 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);
}
Run Code Online (Sandbox Code Playgroud)
使用 RestTemplate 呈现数据流
控制器.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;
}
Run Code Online (Sandbox Code Playgroud)
提供者.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;
}
Run Code Online (Sandbox Code Playgroud)
数据获取器
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;
}
Run Code Online (Sandbox Code Playgroud)
Tho*_*olf 31
由于存在很多误解,所以在这里我要澄清一些事情。
Spring 已正式声明它们将RestTemplate在未来弃用,因此如果可以的话,WebClient如果您想成为未来的证明,请使用它。
注意:从 5.0 开始,非阻塞、反应式
org.springframework.web.reactive.client.WebClient为RestTemplate同步和异步以及流场景提供了有效支持的现代替代方案。该RestTemplate会在未来的版本中被淘汰,并没有重大的新功能的加入前进。有关WebClient更多详细信息和示例代码,请参阅Spring Framework 参考文档部分。
非反应性应用
如果您的应用程序是非响应式应用程序(不向调用客户端返回通量或单声道),您必须做的是在block()需要该值时使用。您当然可以在应用程序内部使用Mono或Flux但最后您必须调用block()以获取需要返回给调用客户端的具体值。
非响应式应用程序tomcat用作底层服务器实现,这是一个基于 servlet 的服务器,将为每个请求分配 1 个线程,因此您不会获得响应式应用程序所获得的性能提升。
反应式应用
另一方面,如果您有一个响应式应用程序,则在任何情况下都不应该调用block()您的应用程序。阻塞正是它所说的,它会阻塞一个线程并阻塞该线程的执行,直到它可以继续,这在反应式世界中是很糟糕的。
您也不应该调用subscribe您的应用程序,除非您的应用程序是响应的最终使用者。例如,如果您正在调用 api 来获取数据并写入您的应用程序所连接的数据库。您的后端应用程序是最终消费者。如果外部客户端正在调用您的后端(例如 React、Angular 应用程序、移动客户端等),则外部客户端是最终消费者,并且是订阅者。不是你。
这里的底层默认服务器实现是一个netty服务器,它是一个非 servlet、基于事件的服务器,它不会为每个请求分配一个线程,服务器本身是线程不可知的,任何可用的线程将在任何请求期间的任何时间处理任何事情。
该webflux文件明确指出,两者的servlet 3.1+支持的服务器Tomcat和码头可webflux以及非serlet服务器网状和暗流中。
我怎么知道我有什么应用程序?
Spring 指出,如果您在类路径上同时拥有spring-web和spring-webflux,则应用程序将支持spring-web并默认启动具有底层 tomcat 服务器的非反应性应用程序。
如果需要作为弹簧状态,可以手动覆盖此行为。
在应用程序中同时添加
spring-boot-starter-web和spring-boot-starter-webflux模块会导致 Spring Boot 自动配置 Spring MVC,而不是 WebFlux。之所以选择这种行为,是因为许多 Spring 开发人员spring-boot-starter-webflux在他们的 Spring MVC 应用程序中添加了使用响应式 WebClient 的内容。您仍然可以通过将所选应用程序类型设置为 来强制您的选择SpringApplication.setWebApplicationType(WebApplicationType.REACTIVE)。
那么如何根据问题提供的代码实现WebClient呢?
@Retryable(maxAttempts = 4,
value = java.net.ConnectException.class,
backoff = @Backoff(delay = 3000, multiplier = 2))
public ResponseEntity<String> getResponse(String url) {
return webClient.get()
.uri(url)
.exchange()
.flatMap(response -> response.toEntity(String.class))
.block();
}
Run Code Online (Sandbox Code Playgroud)
我会说这是最简单和侵入性最小的实现。您当然需要在 a 中构建一个合适的 webclient@Bean并将其自动装配到它的类中。
| 归档时间: |
|
| 查看次数: |
16847 次 |
| 最近记录: |