最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring中WebClient的創(chuàng)建和使用詳解

 更新時(shí)間:2023年11月18日 09:06:29   作者:morris131  
這篇文章主要介紹了Spring中WebClient的創(chuàng)建和使用詳解,在Spring5中,出現(xiàn)了Reactive響應(yīng)式編程思想,并且為網(wǎng)絡(luò)編程提供相關(guān)響應(yīng)式編程的支持,如提供了WebFlux,它是Spring提供的異步非阻塞的響應(yīng)式的網(wǎng)絡(luò)框架,需要的朋友可以參考下

前言

在Spring5中,出現(xiàn)了Reactive響應(yīng)式編程思想,并且為網(wǎng)絡(luò)編程提供相關(guān)響應(yīng)式編程的支持,如提供了WebFlux,它是Spring提供的異步非阻塞的響應(yīng)式的網(wǎng)絡(luò)框架,相比傳統(tǒng)的SpringMVC框架,可以充分利用多CPU并行處理一些功能,雖然不能提高單個(gè)請求的響應(yīng)能力,但是總體可以提高多核的服務(wù)器性能,提高系統(tǒng)吞吐量和伸縮性,特別適合于IO密集型服務(wù)。

WebClient提供的基于響應(yīng)式的非阻塞的Web請求客戶端,相對于傳統(tǒng)的RestTemplate,他不阻塞代碼、異步執(zhí)行。

使用WebClient需要引入下面的依賴:

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

WebClient的創(chuàng)建

WebClient可以直接通過new來創(chuàng)建,也可以使用構(gòu)造者模式來構(gòu)造。

package com.morris.user.demo;

import com.morris.user.entity.Order;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;

import java.util.Arrays;
import java.util.concurrent.TimeUnit;

/**
 * WebClient的創(chuàng)建
 */
public class WebClientDemo1 {

    public static void main(String[] args) throws InterruptedException {
        WebClient webClient = WebClient.create();
        webClient.get().uri("http://127.0.0.1:8020/order/findOrderByUserId?userId={userId}", 1).retrieve()
                .bodyToMono(Order[].class).map(Arrays::asList).subscribe(System.out::println);

        WebClient webClient2 = WebClient.builder()
                .baseUrl("http://127.0.0.1:8020")
                .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                .build();
        webClient2.get().uri("/order/findOrderByUserId?userId={userId}", 1).retrieve()
                .bodyToMono(Order[].class).map(Arrays::asList).subscribe(System.out::println);
        TimeUnit.SECONDS.sleep(5);
    }
}

在應(yīng)用中使用WebClient時(shí)也許你要訪問的URL都來自同一個(gè)應(yīng)用,只是對應(yīng)不同的URI地址,這個(gè)時(shí)候可以把公用的部分抽出來定義為baseUrl,然后在進(jìn)行WebClient請求的時(shí)候只指定相對于baseUrl的URL部分即可。這樣的好處是你的baseUrl需要變更的時(shí)候可以只要修改一處即可。

WebClient發(fā)送Get請求

先創(chuàng)建個(gè)webclient.create()實(shí)例,之后調(diào)用get()、post()等調(diào)用方式,uri()指定路徑,retrieve()用來發(fā)起請求并獲得響應(yīng),bodyToFlux(Order.class)用來將請求結(jié)果需要處理為Order數(shù)組,并包裝為Reactor的Flux對象。

如果返回結(jié)果是一個(gè)JSON字符串,可以使用bodyToMono(),將接收到的JSON字符串轉(zhuǎn)換為對應(yīng)的對象。

如果返回結(jié)果是一個(gè)JSON數(shù)組,可以使用bodyToFlux(),將接收到的JSON數(shù)組轉(zhuǎn)換為對應(yīng)的對象集合,然后依次處理每一個(gè)元素。

package com.morris.user.demo;

import com.morris.user.entity.Order;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;

import java.util.Arrays;
import java.util.concurrent.TimeUnit;

/**
 * WebClient發(fā)送Get請求
 */
public class WebClientGetDemo {

    public static void main(String[] args) throws InterruptedException {
        WebClient webClient = WebClient.create();
        webClient.get().uri("http://127.0.0.1:8020/order/findOrderByUserId?userId={userId}", 1).retrieve()
                .bodyToFlux(Order.class).subscribe(System.out::println);;

        // 休眠一會(huì),否則WebClient中的線程池還沒執(zhí)行,看不到效果
        TimeUnit.SECONDS.sleep(5);
    }
}

WebClient發(fā)送Post請求

可以使用BodyInserters類提供的各種工廠方法來構(gòu)造BodyInserter對象并將其傳遞給body方法。BodyInserters類包含從Object,Publisher,Resource,F(xiàn)ormData,MultipartData等創(chuàng)建BodyInserter的方法。

package com.morris.user.demo;

import com.morris.user.entity.Order;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

/**
 * WebClient發(fā)送Post請求
 */
public class WebClientPostDemo {

    public static void main(String[] args) {
        WebClient webClient = WebClient.create();
        Order order = new Order();
        order.setId(1L);
        order.setUserId(666L);
        order.setGoodName("Iphone 13");
        order.setPrice(9999);
        Mono<Long> mono = webClient.post().uri("http://127.0.0.1:8020/order/saveOrder")
                .body(BodyInserters.fromValue(order))
                // .body(Mono.just(order), Order.class)
                .retrieve()
                .bodyToMono(Long.class);

        // 阻塞等待獲取結(jié)果
        System.out.println(mono.block());
    }
}

WebClient對失敗的處理

package com.morris.user.demo;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClientResponseException;
import reactor.core.publisher.Mono;

/**
 * WebClient對失敗的處理
 */
@Slf4j
public class WebClientDealFailDemo {

    public static void main(String[] args) {
        WebClient webClient = WebClient.create();
        WebClient.ResponseSpec responseSpec = webClient.get().uri("http://127.0.0.1:8020/order/error")
                .retrieve();

        Mono<String> mono = responseSpec
                .onStatus(HttpStatus::is4xxClientError, resp -> {
                    log.error("error4xx:{},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 -> {
                    log.info("ERROR status:{},msg:{}",err.getRawStatusCode(),err.getResponseBodyAsString());
                    throw new RuntimeException(err.getMessage());
                })
                .onErrorReturn("fallback");

        // 阻塞等待獲取結(jié)果
        System.out.println(mono.block());
    }
}

可以使用onStatus根據(jù)響應(yīng)的status code進(jìn)行適配,可以使用doOnError對異常進(jìn)行適配,可以使用onErrorReturn返回默認(rèn)值。

exchange()

retrieve()方法是直接獲取響應(yīng)body,但是,如果需要響應(yīng)的頭信息、Cookie等,可以使用exchange方法,該方法可以訪問整個(gè)ClientResponse。由于響應(yīng)的得到是異步的,所以都可以調(diào)用block()方法來阻塞當(dāng)前程序,等待獲得響應(yīng)的結(jié)果。

package com.morris.user.demo;

import com.morris.user.entity.Order;
import org.springframework.web.reactive.function.client.WebClient;

import java.util.concurrent.TimeUnit;

/**
 * WebClient使用Exchange發(fā)送請求
 */
public class WebClientExchangeDemo {

    public static void main(String[] args) throws InterruptedException {
        WebClient webClient = WebClient.create();
        webClient.get().uri("http://127.0.0.1:8020/order/findOrderByUserId?userId={userId}", 1)
                .exchange()
                .subscribe(r -> {
                    System.out.println(r.headers());
                    r.bodyToFlux(Order.class).subscribe(System.out::println);
                });

        // 休眠一會(huì),否則WebClient中的線程池還沒執(zhí)行,看不到效果
        TimeUnit.SECONDS.sleep(5);
    }
}

filter

WebClient也提供了Filter,對應(yīng)于org.springframework.web.reactive.function.client.ExchangeFilterFunction接口,可以攔截request,也可以攔截response。

package com.morris.user.demo;

import com.morris.user.entity.Order;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

import java.util.concurrent.TimeUnit;

/**
 * WebClient使用filter攔截器
 */
@Slf4j
public class WebClientFilterDemo {

    private static ExchangeFilterFunction logResponseStatus() {
        return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
            log.info("Response Status {}", clientResponse.statusCode());
            return Mono.just(clientResponse);
        });
    }

    public static void main(String[] args) throws InterruptedException {
        WebClient webClient = WebClient.builder().filter(logResponseStatus()).build();
        webClient.get().uri("http://127.0.0.1:8020/order/findOrderByUserId?userId={userId}", 1)
                .exchange()
                .subscribe(r -> {
                    System.out.println(r.headers());
                    r.bodyToFlux(Order.class).subscribe(System.out::println);
                });

        // 休眠一會(huì),否則WebClient中的線程池還沒執(zhí)行,看不到效果
        TimeUnit.SECONDS.sleep(5);
    }
}

Attributes

可以使用attribute在多個(gè)filter之間傳遞參數(shù)。

package com.morris.user.demo;

import com.morris.user.entity.Order;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
 * WebClient使用attribute傳遞參數(shù)
 */
@Slf4j
public class WebClientAttributesDemo {

    private static ExchangeFilterFunction filterRequest() {
        return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
            Optional<Object> myAttribute = clientRequest.attribute("myAttribute");
            System.out.println(myAttribute.get());
            return Mono.just(clientRequest);
        });
    }

    public static void main(String[] args) throws InterruptedException {
        WebClient webClient = WebClient.builder().filter(filterRequest()).build();
        webClient.get().uri("http://127.0.0.1:8020/order/findOrderByUserId?userId={userId}", 1)
                .attribute("myAttribute", "myAttribute")
                .exchange()
                .subscribe(r -> {
                    System.out.println(r.headers());
                    r.bodyToFlux(Order.class).subscribe(System.out::println);
                });

        // 休眠一會(huì),否則WebClient中的線程池還沒執(zhí)行,看不到效果
        TimeUnit.SECONDS.sleep(5);
    }
}

到此這篇關(guān)于Spring中WebClient的創(chuàng)建和使用詳解的文章就介紹到這了,更多相關(guān)WebClient的創(chuàng)建和使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java基于Spire Cloud Excel把Excel轉(zhuǎn)換成PDF

    Java基于Spire Cloud Excel把Excel轉(zhuǎn)換成PDF

    這篇文章主要介紹了Java基于Spire Cloud Excel把Excel轉(zhuǎn)換成PDF,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-05-05
  • java 反射機(jī)制詳解及實(shí)例代碼

    java 反射機(jī)制詳解及實(shí)例代碼

    這篇文章主要介紹了java 反射機(jī)制詳解及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下
    2016-11-11
  • Java?Swing實(shí)現(xiàn)自定義彈窗組件CusDialog(附源碼)

    Java?Swing實(shí)現(xiàn)自定義彈窗組件CusDialog(附源碼)

    Swing 原生對話框 JDialog 和 JFrame 一樣,標(biāo)題欄是系統(tǒng)自帶的,樣式陳舊且無法自定義,下面我們就來看看如何通過Java Swing實(shí)現(xiàn)自定義彈窗組件CusDialog吧
    2026-05-05
  • Windows10系統(tǒng)下修改jar中的文件并重新打包成jar文件然后運(yùn)行的操作步驟

    Windows10系統(tǒng)下修改jar中的文件并重新打包成jar文件然后運(yùn)行的操作步驟

    這篇文章主要介紹了Windows10系統(tǒng)下修改jar中的文件并重新打包成jar文件然后運(yùn)行的操作步驟,文中通過圖文結(jié)合的形式給大家講解的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-08-08
  • SpringCloud微服務(wù)中跨域配置的方法詳解

    SpringCloud微服務(wù)中跨域配置的方法詳解

    在使用SpringCloud實(shí)現(xiàn)微服務(wù)時(shí),經(jīng)常會(huì)碰到前端頁面訪問多個(gè)二級域名的情況,跨域是首先要解決的問題。解決這個(gè)問題,可以從兩方面入手,一種方案是在微服務(wù)各自的業(yè)務(wù)模塊中實(shí)現(xiàn),即在SpringBoot層實(shí)現(xiàn),另外一種方案就是在Gateway層實(shí)現(xiàn)
    2023-02-02
  • 一文搞懂Spring?Security異常處理機(jī)制

    一文搞懂Spring?Security異常處理機(jī)制

    這篇文章主要為大家詳細(xì)介紹一下Spring?Security異常處理機(jī)制,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Spring?Security有一定幫助,感興趣的可以學(xué)習(xí)一下
    2022-07-07
  • SpringAOP核心對象的創(chuàng)建圖解

    SpringAOP核心對象的創(chuàng)建圖解

    這篇文章主要介紹了SpringAOP核心對象的創(chuàng)建詳解,通過使用AOP,我們可以將橫切關(guān)注點(diǎn)(如日志記錄、性能監(jiān)控、事務(wù)管理等)從業(yè)務(wù)邏輯中分離出來,使得代碼更加模塊化、可維護(hù)性更高,需要的朋友可以參考下
    2023-10-10
  • Java C++解決在排序數(shù)組中查找數(shù)字出現(xiàn)次數(shù)問題

    Java C++解決在排序數(shù)組中查找數(shù)字出現(xiàn)次數(shù)問題

    本文終于介紹了分別通過Java和C++實(shí)現(xiàn)統(tǒng)計(jì)一個(gè)數(shù)字在排序數(shù)組中出現(xiàn)的次數(shù)。文中詳細(xì)介紹了實(shí)現(xiàn)思路,感興趣的小伙伴可以跟隨小編學(xué)習(xí)一下
    2021-12-12
  • 在Java中實(shí)現(xiàn)堆排序的步驟詳解

    在Java中實(shí)現(xiàn)堆排序的步驟詳解

    堆排序是一種基于堆數(shù)據(jù)結(jié)構(gòu)的排序算法,堆是一種特殊的完全二叉樹,堆排序利用堆的性質(zhì)通過一系列操作將數(shù)組元素按升序或降序排列,本文給大家介紹了如何在Java中實(shí)現(xiàn)堆排序,需要的朋友可以參考下
    2024-12-12
  • mybatis?mapper.xml中如何根據(jù)數(shù)據(jù)庫類型選擇對應(yīng)SQL語句

    mybatis?mapper.xml中如何根據(jù)數(shù)據(jù)庫類型選擇對應(yīng)SQL語句

    這篇文章主要介紹了mybatis?mapper.xml中如何根據(jù)數(shù)據(jù)庫類型選擇對應(yīng)SQL語句,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01

最新評論

林甸县| 麟游县| 额尔古纳市| 农安县| 闽侯县| 满城县| 浙江省| 贡觉县| 黎城县| 虎林市| 巴林右旗| 偏关县| 麦盖提县| 闵行区| 比如县| 沙坪坝区| 宿迁市| 凤凰县| 新疆| 叙永县| 理塘县| 禹城市| 乐山市| 商丘市| 清丰县| 龙江县| 贡觉县| 曲沃县| 漾濞| 海原县| 英超| 麦盖提县| 东安县| 临颍县| 塔城市| 乐安县| 杭锦旗| 乐平市| 米易县| 措美县| 疏勒县|