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

SpringBoot3-WebClient配置與使用詳解

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

1. 簡介

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

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

2.1 依賴配置

pom.xml中添加必要的依賴:

    <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客戶端
        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)
                // 添加請求日志記錄功能
                .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 請求時(shí),retrieve() 和 exchange() 方法都可以用來處理響應(yīng),但它們有不同的用途和行為。以下是它們的主要區(qū)別:
retrieve()

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

示例對(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 基本請求操作

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請求
    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請求
    public Mono<JSONObject> post(JSONObject body) {
        return webClient.post()
                .uri("/post")
                .bodyValue(body)
                .retrieve()
                .bodyToMono(JSONObject.class);
    }
    // PUT請求
    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請求
    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("客戶端錯(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 {
    // 帶請求頭的請求
    public Mono<JSONObject> getUserWithHeaders(Long id, String token) {
        return webClient.get()
                .uri("/users/{id}", id)
                .header("Authorization", "Bearer " + token)
                .retrieve()
                .bodyToMono(JSONObject.class);
    }
    // 帶查詢參數(shù)的請求
    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)式類型

  • 使用 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("請求超時(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í)曲線較陡平緩
適用場景高并發(fā)、響應(yīng)式系統(tǒng)簡單應(yīng)用、傳統(tǒng)系統(tǒng)

8. 總結(jié)

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

參考資料

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

相關(guān)文章

最新評(píng)論

西宁市| 沅江市| 湘乡市| 六盘水市| 从江县| 民县| 泊头市| 微山县| 土默特左旗| 玉山县| 黑水县| 普兰县| 松原市| 曲松县| 科技| 灵宝市| 重庆市| 卢龙县| 吉林省| 武宁县| 黄山市| 龙井市| 颍上县| 阿拉善盟| 林甸县| 交城县| 韩城市| 安宁市| 巨野县| 徐汇区| 峨山| 冷水江市| 洪雅县| 望江县| 亚东县| 湘阴县| 蓬莱市| 宁晋县| 遂溪县| 融水| 临湘市|