欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot3-WebClient配置與使用詳解

 更新時(shí)間:2024年12月25日 15:15:36   作者:CoderJia  
WebClient是Spring 5引入的響應(yīng)式Web客戶(hù)端,用于執(zhí)行HTTP請(qǐng)求,相比傳統(tǒng)的RestTemplate,WebClient提供了非阻塞、響應(yīng)式的方式來(lái)處理HTTP請(qǐng)求,是Spring推薦的新一代HTTP客戶(hù)端工具,本文將詳細(xì)介紹如何在SpringBoot 3.x中配置和使用WebClient,一起看看吧

1. 簡(jiǎn)介

WebClient是Spring 5引入的響應(yīng)式Web客戶(hù)端,用于執(zhí)行HTTP請(qǐng)求。相比傳統(tǒng)的RestTemplate,WebClient提供了非阻塞、響應(yīng)式的方式來(lái)處理HTTP請(qǐng)求,是Spring推薦的新一代HTTP客戶(hù)端工具。本文將詳細(xì)介紹如何在SpringBoot 3.x中配置和使用WebClient。

2. 環(huán)境準(zhǔn)備

2.1 依賴(lài)配置

pom.xml中添加必要的依賴(lài):

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.10</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>

3. WebClient配置

3.1 基礎(chǔ)配置

@Configuration
public class WebClientConfig {
    @Bean
    public WebClient webClient() {
        return WebClient.builder()
                .baseUrl("https://echo.apifox.com")
                .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
                .build();
    }
}

3.2 高級(jí)配置

package com.coderjia.boot3webflux.config;
import io.netty.channel.ChannelOption;
import io.netty.handler.timeout.ReadTimeoutHandler;
import io.netty.handler.timeout.WriteTimeoutHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import reactor.netty.http.client.HttpClient;
import reactor.netty.resources.ConnectionProvider;
import java.time.Duration;
/**
 * @author CoderJia
 * @create 2024/12/3 下午 09:42
 * @Description
 **/
@Slf4j
@Configuration
public class WebClientConfig {
    @Bean
    public WebClient webClient() {
        // 配置HTTP連接池
        ConnectionProvider provider = ConnectionProvider.builder("custom")
                .maxConnections(500)
                .maxIdleTime(Duration.ofSeconds(20))
                .build();
        // 配置HTTP客戶(hù)端
        HttpClient httpClient = HttpClient.create(provider)
                .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)
                .responseTimeout(Duration.ofSeconds(5))
                .doOnConnected(conn ->
                        conn.addHandlerLast(new ReadTimeoutHandler(5))
                                .addHandlerLast(new WriteTimeoutHandler(5)));
        // 構(gòu)建WebClient實(shí)例
        return WebClient.builder()
                .clientConnector(new ReactorClientHttpConnector(httpClient))
                .baseUrl("https://echo.apifox.com")
                .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
                // 添加請(qǐng)求日志記錄功能
                .filter(ExchangeFilterFunction.ofRequestProcessor(
                        clientRequest -> {
                            log.debug("Request: {} {}",
                                    clientRequest.method(),
                                    clientRequest.url());
                            return Mono.just(clientRequest);
                        }
                ))
                // 添加響應(yīng)日志記錄功能
                .filter(ExchangeFilterFunction.ofResponseProcessor(
                        clientResponse -> {
                            log.debug("Response status: {}",
                                    clientResponse.statusCode());
                            return Mono.just(clientResponse);
                        }
                ))
                .build();
    }
}

3.3 retrieve()和exchange()區(qū)別

在使用 WebClient 進(jìn)行 HTTP 請(qǐng)求時(shí),retrieve() 和 exchange() 方法都可以用來(lái)處理響應(yīng),但它們有不同的用途和行為。以下是它們的主要區(qū)別:
retrieve()

  • 用途:retrieve() 方法用于簡(jiǎn)化響應(yīng)處理,特別是當(dāng)你只需要響應(yīng)體時(shí)。
  • 自動(dòng)錯(cuò)誤處理:retrieve() 會(huì)自動(dòng)處理 HTTP 錯(cuò)誤狀態(tài)碼(例如 4xx 和 5xx),并拋出 WebClientResponseException 及其子類(lèi)。
  • 返回值:通常用于直接獲取響應(yīng)體,例如 bodyToMono(String.class) 或 bodyToFlux(String.class)。
  • 適用場(chǎng)景:適用于大多數(shù)常見(jiàn)的請(qǐng)求處理場(chǎng)景,特別是當(dāng)你不需要手動(dòng)處理響應(yīng)狀態(tài)碼時(shí)。

exchange()

  • 用途:exchange() 方法提供了更底層的控制,允許你手動(dòng)處理響應(yīng),包括響應(yīng)狀態(tài)碼和響應(yīng)頭。
  • 手動(dòng)錯(cuò)誤處理:exchange() 不會(huì)自動(dòng)處理 HTTP 錯(cuò)誤狀態(tài)碼,你需要手動(dòng)檢查響應(yīng)狀態(tài)碼并進(jìn)行相應(yīng)的處理。
  • 返回值:返回 ClientResponse 對(duì)象,你可以從中提取響應(yīng)狀態(tài)碼、響應(yīng)頭和響應(yīng)體。
  • 適用場(chǎng)景:適用于需要手動(dòng)處理響應(yīng)狀態(tài)碼或響應(yīng)頭的復(fù)雜場(chǎng)景。

示例對(duì)比

retrieve()

public Mono<JSONObject> get(String q1) {
    return webClient.get()
            .uri(uriBuilder -> uriBuilder
                    .path("/get")
                    .queryParam("q1", q1)
                    .build())
            .accept(MediaType.APPLICATION_JSON)
            .retrieve()
            .bodyToMono(JSONObject.class);
}

exchange()

public Mono<JSONObject> get(String q1) {
    return webClient.get()
            .uri(uriBuilder -> uriBuilder
                    .path("/get")
                    .queryParam("q1", q1)
                    .build())
            .accept(MediaType.APPLICATION_JSON)
            .exchangeToMono(response -> {
                if (response.statusCode().is2xxSuccessful()) {
                    return response.bodyToMono(JSONObject.class);
                } else {
                    return Mono.error(new RuntimeException("Request failed with status code: " + response.statusCode()));
                }
            });
}

4. 使用示例

4.1 基本請(qǐng)求操作

package com.coderjia.boot3webflux.service;
import com.alibaba.fastjson.JSONObject;
import jakarta.annotation.Resource;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
/**
 * @author CoderJia
 * @create 2024/12/3 下午 10:22
 * @Description
 **/
@Service
public class ApiService {
    @Resource
    private WebClient webClient;
    // GET請(qǐng)求
    public Mono<JSONObject> get(String q1) {
        return webClient.get()
                .uri(uriBuilder -> uriBuilder
                        .path("/get")
                        .queryParam("q1", q1)
                        .build())
                .accept(MediaType.APPLICATION_JSON)
                .retrieve()
                .bodyToMono(JSONObject.class);
    }
    // POST請(qǐng)求
    public Mono<JSONObject> post(JSONObject body) {
        return webClient.post()
                .uri("/post")
                .bodyValue(body)
                .retrieve()
                .bodyToMono(JSONObject.class);
    }
    // PUT請(qǐng)求
    public Mono<JSONObject> put(String q1, JSONObject JSONObject) {
        return webClient.put()
                .uri(uriBuilder -> uriBuilder
                        .path("/put")
                        .queryParam("q1", q1)
                        .build())
                .bodyValue(JSONObject)
                .retrieve()
                .bodyToMono(JSONObject.class);
    }
    // DELETE請(qǐng)求
    public Mono<JSONObject> delete(String q1) {
        return webClient.delete()
                .uri(uriBuilder -> uriBuilder
                        .path("/delete")
                        .queryParam("q1", q1)
                        .build())
                .retrieve()
                .bodyToMono(JSONObject.class);
    }
}

效果展示

get

post

put

delete

4.2 處理復(fù)雜響應(yīng)

@Service
public class ApiService {
    // 獲取列表數(shù)據(jù)
    public Flux<JSONObject> getAllUsers() {
        return webClient.get()
                .uri("/users")
                .retrieve()
                .bodyToFlux(JSONObject.class);
    }
    // 處理錯(cuò)誤響應(yīng)
    public Mono<JSONObject> getUserWithErrorHandling(Long id) {
        return webClient.get()
                .uri("/users/{id}", id)
                .retrieve()
                .onStatus(HttpStatusCode::is4xxClientError, clientResponse -> Mono.error(new RuntimeException("客戶(hù)端錯(cuò)誤")))
                .onStatus(HttpStatusCode::is5xxServerError, clientResponse -> Mono.error(new RuntimeException("服務(wù)器錯(cuò)誤")))
                .bodyToMono(JSONObject.class);
    }
    // 使用exchange()方法獲取完整響應(yīng)
    public Mono<ResponseEntity<JSONObject>> getUserWithFullResponse(Long id) {
        return webClient.get()
                .uri("/users/{id}", id)
                .accept(MediaType.APPLICATION_JSON)
                .exchange()
                .flatMap(response -> response.toEntity(JSONObject.class));
    }
}

4.3 高級(jí)用法

@Service
public class ApiService {
    // 帶請(qǐng)求頭的請(qǐng)求
    public Mono<JSONObject> getUserWithHeaders(Long id, String token) {
        return webClient.get()
                .uri("/users/{id}", id)
                .header("Authorization", "Bearer " + token)
                .retrieve()
                .bodyToMono(JSONObject.class);
    }
    // 帶查詢(xún)參數(shù)的請(qǐng)求
    public Flux<JSONObject> searchUsers(String name, int age) {
        return webClient.get()
                .uri(uriBuilder -> uriBuilder
                        .path("/users/search")
                        .queryParam("name", name)
                        .queryParam("age", age)
                        .build())
                .retrieve()
                .bodyToFlux(JSONObject.class);
    }
    // 文件上傳
    public Mono<String> uploadFile(FilePart filePart) {
        return webClient.post()
                .uri("/upload")
                .contentType(MediaType.MULTIPART_FORM_DATA)
                .body(BodyInserters.fromMultipartData("file", filePart))
                .retrieve()
                .bodyToMono(String.class);
    }
}

5. 最佳實(shí)踐

合理使用響應(yīng)式類(lèi)型

  • 使用 Mono 用于單個(gè)對(duì)象
  • 使用 Flux 用于集合數(shù)據(jù)
  • 注意背壓處理

錯(cuò)誤處理

 public Mono<JSONObject> getUserWithRetry(Long id) {
     return webClient.get()
             .uri("/users/{id}", id)
             .retrieve()
             .bodyToMono(JSONObject.class)
             .retryWhen(Retry.backoff(3, Duration.ofSeconds(1)))
             .timeout(Duration.ofSeconds(5))
             .onErrorResume(TimeoutException.class,
                     e -> Mono.error(new RuntimeException("請(qǐng)求超時(shí)")));
 }

資源管理

  • 使用連接池
  • 設(shè)置適當(dāng)?shù)某瑫r(shí)時(shí)間
  • 實(shí)現(xiàn)優(yōu)雅關(guān)閉

6. 注意事項(xiàng)

  • WebClient 是非阻塞的,需要注意響應(yīng)式編程的特性
  • 合理配置連接池和超時(shí)參數(shù)
  • 在生產(chǎn)環(huán)境中實(shí)現(xiàn)適當(dāng)?shù)腻e(cuò)誤處理和重試機(jī)制
  • 注意內(nèi)存使用,特別是處理大量數(shù)據(jù)時(shí)

7. 與RestTemplate對(duì)比

特性WebClientRestTemplate
編程模型響應(yīng)式、非阻塞同步、阻塞
性能更好一般
資源利用更高效一般
學(xué)習(xí)曲線較陡平緩
適用場(chǎng)景高并發(fā)、響應(yīng)式系統(tǒng)簡(jiǎn)單應(yīng)用、傳統(tǒng)系統(tǒng)

8. 總結(jié)

WebClient 作為 Spring 推薦的新一代 HTTP 客戶(hù)端,提供了強(qiáng)大的響應(yīng)式編程能力和更好的性能。雖然相比 RestTemplate 有一定的學(xué)習(xí)曲線,但在現(xiàn)代微服務(wù)架構(gòu)中,其帶來(lái)的好處遠(yuǎn)超過(guò)學(xué)習(xí)成本。建議在新項(xiàng)目中優(yōu)先考慮使用WebClient,特別是在需要處理高并發(fā)請(qǐng)求的場(chǎng)景下。

參考資料

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

相關(guān)文章

  • 解析Java繼承中方法的覆蓋和重載

    解析Java繼承中方法的覆蓋和重載

    這篇文章主要介紹了Java繼承中方法的覆蓋和重載的詳細(xì)概念及用法,非常的實(shí)用,這里推薦給大家,有需要的小伙伴可以參考下。
    2015-05-05
  • Spring boot使用多線程過(guò)程步驟解析

    Spring boot使用多線程過(guò)程步驟解析

    這篇文章主要介紹了Spring boot使用多線程過(guò)程步驟解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • 詳解Spring Boot最核心的27個(gè)注解,你了解多少?

    詳解Spring Boot最核心的27個(gè)注解,你了解多少?

    這篇文章主要介紹了詳解Spring Boot最核心的27個(gè)注解,你了解多少?文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • Spring Boot @Async 異步任務(wù)執(zhí)行方法

    Spring Boot @Async 異步任務(wù)執(zhí)行方法

    本篇文章主要介紹了Spring Boot @Async 異步任務(wù)執(zhí)行方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-05-05
  • Java自動(dòng)生成趨勢(shì)比對(duì)數(shù)據(jù)的方法分享

    Java自動(dòng)生成趨勢(shì)比對(duì)數(shù)據(jù)的方法分享

    這篇文章主要和大家分享了一種Java自動(dòng)生成趨勢(shì)比對(duì)數(shù)據(jù)的方法設(shè)計(jì)及實(shí)現(xiàn),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-04-04
  • SSH框架網(wǎng)上商城項(xiàng)目第22戰(zhàn)之銀行圖標(biāo)以及支付頁(yè)面顯示

    SSH框架網(wǎng)上商城項(xiàng)目第22戰(zhàn)之銀行圖標(biāo)以及支付頁(yè)面顯示

    這篇文章主要為大家詳細(xì)介紹了SSH框架網(wǎng)上商城項(xiàng)目第22戰(zhàn)之銀行圖標(biāo)以及支付頁(yè)面顯示,感興趣的小伙伴們可以參考一下
    2016-06-06
  • Spring運(yùn)行時(shí)動(dòng)態(tài)注冊(cè)bean的方法

    Spring運(yùn)行時(shí)動(dòng)態(tài)注冊(cè)bean的方法

    這篇文章主要介紹了Spring運(yùn)行時(shí)動(dòng)態(tài)注冊(cè)bean的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08
  • Java實(shí)現(xiàn)Excel文件加密解密的示例代碼

    Java實(shí)現(xiàn)Excel文件加密解密的示例代碼

    設(shè)置excel文件保護(hù)時(shí),通??蛇x擇對(duì)整個(gè)工作簿進(jìn)行加密保護(hù)。無(wú)需設(shè)置文檔保護(hù)時(shí),可撤銷(xiāo)密碼保護(hù),即解密文檔。本文將通過(guò)java程序演示以上加密、解密方法的實(shí)現(xiàn),感興趣的可以了解一下
    2022-05-05
  • 實(shí)例詳解MyBatis-plus自動(dòng)填充功能

    實(shí)例詳解MyBatis-plus自動(dòng)填充功能

    每次對(duì)數(shù)據(jù)進(jìn)行新增、刪除、修改時(shí)都需要對(duì)這些字段進(jìn)行設(shè)置,雖然新增時(shí)間和修改時(shí)間可以使用數(shù)據(jù)庫(kù)的時(shí)間,但是新增人和修改人就不能使用這樣的功能,下面小編給大家介紹下MyBatis-plus自動(dòng)填充功能的實(shí)例代碼,感興趣的朋友一起看看吧
    2022-01-01
  • 關(guān)于Java Interface接口的簡(jiǎn)單練習(xí)題

    關(guān)于Java Interface接口的簡(jiǎn)單練習(xí)題

    這篇文章主要給大家分享的是關(guān)于Java Interface接口的簡(jiǎn)單練習(xí)題,難度不算大,但是要有一個(gè)清晰的邏輯建立接口和鏈接Java類(lèi)。下面來(lái)看看文章的詳細(xì)介紹吧,需要的朋友可以參考一下
    2021-11-11

最新評(píng)論