WebClient: Spring的新的HTTP反應式客戶端 - spring.io

banq發表於2021-01-12

今天,我們將研究一個多功能的,方便的,花哨的HTTP客戶端WebClient。
HTTP服務是常見的資料來源。Web是HTTP可伸縮性和彈性的存在證明,在構建網路服務時,它非常有力地證明了對HTTP約束(如REST)的吸引力。
有一些很棒的庫(例如Apache HttpComponents ClientOkHttp)以相同的方式工作。WebClient是在Spring Webflux中使用基於Netty的非阻塞HTTP客戶端.
WebClient是反應性的,無阻塞的,用來替代RestTemplate。因為它是非阻塞的:用於發出網路請求的客戶端執行緒不會結束通話以等待網路服務響應。這意味著更好的可伸縮性,它使用了Reactive Streams API,使編寫變得更加容易.WebClient可以與任何舊的HTTP端點進行通訊.
 
使用WebClient需要引入依賴:org.springframework.boot : spring-boot-starter-webflux
下面是WebClient程式碼演示的功能:
  • 使用支援Spring Initializr的HTTP API初始化了一個新專案
  • 它使用Spring API檢索所有活動的開源Spring專案


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
 

相關文章