Original: Curly brace MC(wechat official account: Huakuohao-MC), welcome to share, please keep the source.

WebClient is an HTTP call client introduced in Spring5 based on responsive programming. Spring officially recommends using WebClient instead of RestTemplate for HTTP calls. Since WebClient is based on Reactor implementation, it can support both blocking calls and non-blocking calls, making resource utilization higher in high concurrency scenarios. This is one of the important reasons why it is officially recommended.

If you are not familiar with reactive programming, I strongly recommend that you take a look at this article, which will help you with the sample code in this article.

If you want to use WebClient in your project, add the following dependencies to the Pom file

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
Copy the code

If you are using Gradle, add the following dependencies

dependencies {
    compile 'org.springframework.boot:spring-boot-starter-webflux'
    }
Copy the code

Initialize the WebClient

  1. Initialize directly, without any arguments.
    WebClient client = WebClient.create();
Copy the code
  1. When initialized, a default call address is provided.
WebClient client = WebClient.create("http://localhost:8080");
Copy the code
  1. Custom parameter initialization.
WebClient client = WebClient.builder()
    .baseUrl("http://localhost:8080")
    .defaultCookie("cookieKey"."cookieValue")
    .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
    .defaultUriVariables(Collections.singletonMap("url"."http://localhost:8080"))
    .build();
Copy the code
  1. Change the default timeout period.
// Set the timeout through HttpClient
HttpClient httpClient = HttpClient.create()
    // Set connection timeout
    .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)
    // Set the response timeout
    .responseTimeout(Duration.ofMillis(5000))
    // Set read and write timeout periods respectively
    .doOnConnected(conn -> conn.addHandlerLast(new          ReadTimeoutHandler(5000, TimeUnit.MILLISECONDS))     .addHandlerLast(new WriteTimeoutHandler(5000,TimeUnit.MILLISECONDS))); 
    
WebClient client = WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
Copy the code

Making a Get request

  1. Block to get 0 or 1 return resultMonosaid
// Initialize with builder
WebClientWebClient webClient = WebClient.builder()        // Configure the header information
.defaultHeader(HttpHeaders.ACCEPT_CHARSET, "UTF-8")
// Define the filter
.filter(ExchangeFilterFunctions.basicAuthentication("user"."password"))
.filter((clientRequest, next) -> {           
        logger.info("Request: {} {}",clientRequest.method(),clientRequest.url());
clientRequest.headers()
        .forEach((name, values) -> values.forEach(value 
-> logger.info("{} = {}", name, value)));
return next.exchange(clientRequest);
})
.build();
// Initiate a GET request
Mono<String> resp = webClient.get()
.uri("https://localhost:8080"// Get the result
.retrieve()
// Convert the result to the specified type
.bodyToMono(String.class);
// Block to print the result
logger.info("result:{}",resp.block());
Copy the code
  1. To block multiple returns, useFluxsaid
Flux<Book> bookFlux = WebClient.create()
                          .method(HttpMethod.GET)
                         .uri("http://localhost:8080/books")
                         .retrieve()
                         .bodyToFlux(Book.class);
 // Get the response result by blocking
 List<Book> books = bookFlux.collectList().block();
 // Get the response in a non-blocking waybookFlux.subscribe(book ->{System.out.print(book.getName()); });Copy the code
  1. Get the response in a non-blocking manner
Flux<Book> bookFlux = WebClient.create()
                          .method(HttpMethod.GET)
                         .uri("http://localhost:8080/books")
                         .retrieve()
                         .bodyToFlux(Book.class);

 // Get the response in a non-blocking waybookFlux.subscribe(book ->{System.out.print(book.getName()); });Copy the code
  1. Pass the parameter by placeholder symbol
Mono<String> mono = WebClient.create()
                    .method(HttpMethod.POST)
                  .uri("http://localhost:8080/book/{id}/{name}"."1"."java")
                  .retrieve()
                  .bodyToMono(String.class);
                  String result = mono.block();
Copy the code

In addition to placeholder parameters, you can also pass parameters in the form of map, etc., here is not an example to introduce.

Making a POST request

  1. initiatePOSTRequest, submitFormThe form
MultiValueMap<String, String> formData = new 
LinkedMultiValueMap<>();
formData.add("name1"."value1");
formData.add("name2"."value2");
Mono<String> resp = WebClient.create().post()
                    .uri("http://localhost:8080/submit")            .contentType(MediaType.APPLICATION_FORM_URLENCODED)
                    .body(BodyInserters.fromFormData(formData))        .retrieve().bodyToMono(String.class);
                    logger.info("result:{}",resp.block());
 
Copy the code
  1. useRaw JsonIn the manner of initiatingPOSTThe request.
Mono<String> resp = WebClient.create().post()
                    .uri("http://localhost:8080/book/json")
                                                                    .contentType(MediaType.APPLICATION_JSON)
                                                                    .body(BodyInserters.fromValue("{\n" +                " \"name\" : \"java\",\n" +                "\"price\ : \"32.5\" \n" +                "}"))        .retrieve().bodyToMono(String.class);

logger.info("result:{}",resp.block());
Copy the code

Error and exception handling

WebClient can handle errors and exceptions more gracefully.

/ / create the WebClient
        WebClient webClient = WebClient.builder()
                .baseUrl("http://localhost:8080")
                .defaultHeader(HttpHeaders.CONTENT_TYPE, "application/json")
                .defaultHeader(HttpHeaders.ACCEPT_CHARSET, "UTF-8")
                .build();

        // Initiate a Get request
        WebClient.ResponseSpec responseSpec = webClient.method(HttpMethod.GET)
                .uri("/book/remark/{id}"."1")
                .retrieve();

        // Respond according to the status code
        Mono<String> mono = responseSpec
                .onStatus(e -> e.is4xxClientError(),resp -> {
                    logger.error("error:{},msg:{}",resp.statusCode().value(),resp.statusCode().getReasonPhrase());
                    return Mono.error(new RuntimeException(resp.statusCode().value() + ":" + resp.statusCode().getReasonPhrase()));
                })
                .bodyToMono(String.class)
                .doOnError(WebClientResponseException.class, err -> {
                    logger.info("ERROR status:{},msg:{}",err.getRawStatusCode(),err.getResponseBodyAsString());
                    throw new RuntimeException(err.getMessage());
                })
                .onErrorReturn("fallback");
        String result = mono.block();
        logger.info("result:{}",result);
Copy the code

conclusion

Above is some WebClient use small Demo, hope to those who want to understand WebClient some help. If you want to know more, it is recommended to read the official documentation.

Recommended reading

1. Java concurrent programming stuff (10) — Final summary

2. Common network problem locating tools that programmers should master

3. Do you know how to use Awk

4. Teach you how to build a set of ELK log search operation and maintenance platform

Original: Curly brace MC(wechat official account: Huakuohao-MC) Focus on JAVA basic programming and big data, focus on experience sharing and personal growth.