Когда WebClient все еще использует RestTemplate?

задняя часть Spring

Оригинал: фигурные скобки MC (публичная учетная запись WeChat: huakuohao-mc), добро пожаловать в общий доступ, пожалуйста, сохраните источник для перепечатки.

WebClientдаSpring5Представлено на основе реактивного программированияHTTPпозвонить клиенту.SpringОфициально рекомендуетсяWebClientальтернативаRestTemplateЗаканчиватьHTTPперечислить. потому чтоWebClientосновывается наReactorТаким образом, он может поддерживать как блокирующие, так и неблокирующие вызовы, а использование ресурсов выше в сценариях с высокой степенью параллелизма. Это также является одной из важных причин официальной рекомендации.

Если вы не понимаете реактивного программирования, я настоятельно рекомендую вам сначала взглянуть на меня.эта статья, который также будет полезен для примера кода в этой статье.

Если вы хотите использовать его в проектеWebClient,существуетPomДобавьте в файл следующие зависимости

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

При использованииGradle, затем добавьте следующие зависимости

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

Инициализировать веб-клиент

  1. Прямая инициализация без каких-либо параметров.
    WebClient client = WebClient.create();
  1. При инициализации укажите адрес вызова по умолчанию.
WebClient client = WebClient.create("http://localhost:8080");
  1. Инициализация пользовательского параметра.
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();
  1. Измените период ожидания по умолчанию.
//通过HttpClient设置超时时间
HttpClient httpClient = HttpClient.create()
    //设置连接超时时间
    .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)
    //设置响应超时时间
    .responseTimeout(Duration.ofMillis(5000))
    //分别设置读写超时时间
    .doOnConnected(conn -> conn.addHandlerLast(new          ReadTimeoutHandler(5000, TimeUnit.MILLISECONDS))     .addHandlerLast(new WriteTimeoutHandler(5000,TimeUnit.MILLISECONDS))); 
    
WebClient client = WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();

Сделать запрос на получение

  1. Чтобы получить 0 или 1 возвращаемый результат блокирующим способом, используйтеMonoвыражать
//通过builder的方式初始化
WebClientWebClient webClient = WebClient.builder()        //配置头部信息  
.defaultHeader(HttpHeaders.ACCEPT_CHARSET, "UTF-8")
//定义过滤器        
.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();
//发起GET请求
Mono<String> resp = webClient.get()
.uri("https://localhost:8080") 
//获取结果 
.retrieve()
//将结果转化为指定类型 
.bodyToMono(String.class);
//以阻塞的方式将结果打印出来
logger.info("result:{}",resp.block());
  1. Чтобы получить несколько возвращаемых результатов блокирующим способом, используйтеFluxвыражать
Flux<Book> bookFlux = WebClient.create()
                          .method(HttpMethod.GET)
                         .uri("http://localhost:8080/books")
                         .retrieve()
                         .bodyToFlux(Book.class);
 //通过阻塞的方式获取响应结果
 List<Book> books = bookFlux.collectList().block();
 //通过非阻塞的方式获取响应结果
 bookFlux.subscribe(book ->{System.out.print(book.getName());});
  1. Получите результат ответа неблокирующим способом
Flux<Book> bookFlux = WebClient.create()
                          .method(HttpMethod.GET)
                         .uri("http://localhost:8080/books")
                         .retrieve()
                         .bodyToFlux(Book.class);

 //通过非阻塞的方式获取响应结果
 bookFlux.subscribe(book ->{System.out.print(book.getName());});
  1. Передача параметров через заполнители
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();

В дополнение к параметрам-заполнителям вы также можете передавать параметры в виде карты и т. д., которые не будут здесь представлены по одному.

Сделать POST-запрос

  1. положить началоPOSTзапросить, подать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());
 
  1. использоватьRaw Jsonспособ инициироватьPOSTпросить.
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());

Обработка ошибок и исключений

WebClient может более изящно обрабатывать ошибки и исключения.

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

        //发起Get请求
        WebClient.ResponseSpec responseSpec = webClient.method(HttpMethod.GET)
                .uri("/book/remark/{id}", "1")
                .retrieve();

        //根据状态码进行响应
        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);

Суммировать

выше некоторыеWebClientб/у маленькийDemo, надеюсь для тех, кто хочет знатьWebClientодноклассники с некоторой помощью. Если вы хотите узнать больше, рекомендуется ознакомиться с официальной документацией.

Рекомендуемое чтение

1. Те ​​вещи о параллельном программировании на Java (10) — окончательный итог

2. Общие инструменты обнаружения сетевых проблем, которыми должны овладеть программисты

3. Вы умеете пользоваться этим древним оружием Авка?

4. Научите вас создавать набор операций поиска и обслуживания журналов ELK.

Оригинал: Curly Brackets MC (публичная учетная запись WeChat: huakuohao-mc). Сосредоточьтесь на базовом программировании JAVA и больших данных, сосредоточьтесь на обмене опытом и личном росте.