今天,我们将研究一个多功能的,方便的,花哨的HTTP客户端WebClient。
HTTP服务是常见的数据源。Web是HTTP可伸缩性和弹性的存在证明,在构建网络服务时,它非常有力地证明了对HTTP约束(如REST)的吸引力。
有一些很棒的库(例如Apache HttpComponents Client和OkHttp)以相同的方式工作。WebClient是在Spring Webflux中使用基于Netty的非阻塞HTTP客户端.
WebClient是反应性的,无阻塞的,用来替代RestTemplate。因为它是非阻塞的:用于发出网络请求的客户端线程不会挂断以等待网络服务响应。这意味着更好的可伸缩性,它使用了Reactive Streams API,使编写变得更加容易.WebClient可以与任何旧的HTTP端点进行通信.
使用WebClient需要引入依赖:org.springframework.boot : spring-boot-starter-webflux
下面是WebClient代码演示的功能:
package bootiful.httpclient.webclient;
import lombok.ToString; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.ApplicationListener; import org.springframework.context.annotation.Bean; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBufferUtils; import org.springframework.http.MediaType; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono;
import java.net.URI; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection;
import static java.nio.file.StandardOpenOption.CREATE;
@EnableAsync @SpringBootApplication public class BootifulApplication {
public static void main(String[] args) { SpringApplication.run(BootifulApplication.class, args); }
@Bean WebClient webClient(WebClient.Builder builder) { return builder// .filter(// (clientRequest, exchangeFunction) -> exchangeFunction// .exchange(clientRequest)// .doOnNext(response -> System.out.println("got a WebClient response: " + response))// ) // .build(); }
@Bean ApplicationListener<ApplicationReadyEvent> ready(@Value("file://${user.home}/Desktop/output.zip") Path output, WebClient client) {
return event -> {
// initialize a new Spring Boot project .zip archive Mono<DataBuffer> db = client.get()// .uri(URI.create("https://start.spring.io/starter.zip"))// .accept(MediaType.APPLICATION_OCTET_STREAM)// .retrieve()// .bodyToMono(DataBuffer.class);
// gets written out to ~/output.zip Mono<Boolean> write = DataBufferUtils.write(db, output, CREATE).thenReturn(true);
// enumerate all the active Spring projects using the // JSON API while we're at it... Mono<ProjectsResponse> json = client// .get()// .uri(URI.create("https://spring.io/api/projects"))// .retrieve()// .bodyToMono(ProjectsResponse.class);
// look ma! No threading code! this will launch both network // calls (the .zip and the json) at the same time Mono.zip(write, json).subscribe(tuple -> enumerate(tuple.getT2())); }; }
private void enumerate(ProjectsResponse pr) { pr._embedded // .projects // .stream() // .filter(p -> p.status.equalsIgnoreCase("active")) // .forEach(project -> System.out.println(project.toString())); }
}
@ToString class ProjectsResponse {
public Embedded _embedded = new Embedded();
@ToString public static class Project {
public String name, slug, status, repositoryUrl;
}
@ToString public static class Embedded {
public Collection<Project> projects = new ArrayList<>();
}
}
|
您想引入WebClient,但不想使用其余的反应式Web堆栈,则需要告诉Spring Boot。否则,Spring Boot将尝试建立基于Netty的Spring Webflux环境。
需要以下配置application.properties:
spring.main.web-application-type=none