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

Java 響應(yīng)式編程與 Spring WebFlux深入探討

 更新時(shí)間:2025年09月15日 10:40:04   作者:M_Reus_11  
響應(yīng)式編程是一種基于異步數(shù)據(jù)流(Asynchronous Data Streams)和變化傳播(Propagation of Change)的編程范式,本文給大家介紹Java響應(yīng)式編程與Spring WebFlux的相關(guān)知識(shí),感興趣的朋友一起看看吧

第一部分:響應(yīng)式編程 (Reactive Programming) 核心思想

要理解 WebFlux,必須先理解其背后的編程范式——響應(yīng)式編程。

1. 什么是響應(yīng)式編程?

響應(yīng)式編程是一種基于異步數(shù)據(jù)流(Asynchronous Data Streams)和變化傳播(Propagation of Change)的編程范式。這意味著它可以自動(dòng)地將變化推送給消費(fèi)者,而不是讓消費(fèi)者主動(dòng)去等待或輪詢變化。

簡(jiǎn)單比喻:

  • 傳統(tǒng) imperative(命令式)編程:像是去餐館點(diǎn)餐,你(調(diào)用者)點(diǎn)完餐后,就一直坐在那里等,直到服務(wù)員(被調(diào)用者)把菜端上來(lái)。在這期間你幾乎不能做別的事(阻塞)。
  • 響應(yīng)式編程:像是取號(hào)等位。你拿到號(hào)后(訂閱一個(gè)事件),就可以去干別的事情(比如玩手機(jī))。當(dāng)座位準(zhǔn)備好時(shí),系統(tǒng)會(huì)通知你(回調(diào)你的函數(shù))。在這個(gè)過(guò)程中,你沒有阻塞等待。

2. 核心動(dòng)機(jī):解決高并發(fā)與高效資源利用

在傳統(tǒng)的同步阻塞式模型(如 Spring MVC + Servlet Tomcat)中,每個(gè)請(qǐng)求都會(huì)綁定一個(gè)線程。當(dāng)遇到高并發(fā)或慢速的 I/O 操作(如數(shù)據(jù)庫(kù)查詢、網(wǎng)絡(luò)調(diào)用)時(shí),線程會(huì)被大量占用并阻塞,導(dǎo)致線程池耗盡,無(wú)法處理新的請(qǐng)求,從而限制應(yīng)用的擴(kuò)展性。

響應(yīng)式編程的目標(biāo)是使用更少的線程(通常是 CPU 核心數(shù))來(lái)處理更高的并發(fā)。它通過(guò)在 I/O 操作發(fā)生時(shí)讓出線程去處理其他任務(wù),并在操作完成后通過(guò)回調(diào)的方式通知,從而極大地提高了線程的利用率。

3. 響應(yīng)式流 (Reactive Streams) 規(guī)范

這是一個(gè)由 Netflix、Pivotal 等公司共同制定的規(guī)范,定義了 JVM 上響應(yīng)式編程庫(kù)的標(biāo)準(zhǔn)。它包含了四個(gè)核心接口:

  • Publisher(發(fā)布者):生產(chǎn)者,是數(shù)據(jù)的源頭。它根據(jù)需求發(fā)布數(shù)據(jù)。它只有一個(gè)方法:subscribe(Subscriber<? super T> s)
  • Subscriber(訂閱者):消費(fèi)者,接收并處理數(shù)據(jù)。它有四個(gè)方法:
    • onSubscribe(Subscription s): 在訂閱開始時(shí)被調(diào)用,參數(shù) Subscription 用于控制流量。
    • onNext(T t): 接收一條數(shù)據(jù)。
    • onError(Throwable t): 在發(fā)生錯(cuò)誤時(shí)被調(diào)用。
    • onComplete(): 在數(shù)據(jù)流全部發(fā)送完畢時(shí)被調(diào)用。
  • Subscription(訂閱):代表一個(gè)訂閱關(guān)系。它提供了請(qǐng)求數(shù)據(jù)和取消訂閱的方法:
    • request(long n): 請(qǐng)求 n 條數(shù)據(jù)(背壓的核心)。
    • cancel(): 取消訂閱,停止接收數(shù)據(jù)。
  • Processor(處理器):同時(shí)扮演 Publisher 和 Subscriber 的角色,用于轉(zhuǎn)換數(shù)據(jù)流。

核心思想:拉取模式 (Pull-based) 與背壓 (Backpressure)
訂閱者通過(guò) Subscription.request(n) 主動(dòng)請(qǐng)求數(shù)據(jù),而不是發(fā)布者無(wú)限制地推送。這允許消費(fèi)者根據(jù)自己的處理能力來(lái)控制數(shù)據(jù)流入的速度,從而避免了被快速的生產(chǎn)者壓垮,這就是背壓機(jī)制。

第二部分:Project Reactor - WebFlux 的響應(yīng)式核心庫(kù)

Spring WebFlux 默認(rèn)內(nèi)置并依賴于 Project Reactor,這是一個(gè)完全遵循 Reactive Streams 規(guī)范的響應(yīng)式庫(kù)。它提供了兩個(gè)核心類型:

1.Mono

代表 0 或 1 個(gè)元素的異步序列。

  • 用于返回單個(gè)結(jié)果,類似于 Optional 或 CompletableFuture
  • 示例:根據(jù) ID 查詢一個(gè)用戶、執(zhí)行一個(gè)保存操作(返回保存的對(duì)象)。
Mono<User> userMono = userRepository.findById(1L);
Mono<Void> deleteMono = userRepository.deleteById(1L); // 可能沒有返回值

2.Flux

代表 0 到 N 個(gè)元素的異步序列。

  • 用于返回多個(gè)結(jié)果,類似于 List、Stream。
  • 示例:獲取所有用戶、獲取一個(gè)不斷輸出的股票價(jià)格流。
Flux<User> userFlux = userRepository.findAll();
Flux<StockPrice> stockPriceFlux = getStockPriceStream("AAPL");

3. 操作符 (Operators)

Reactor 提供了極其豐富的操作符,用于構(gòu)建、轉(zhuǎn)換、過(guò)濾、組合數(shù)據(jù)流,類似于 Java 8 Stream API,但是為異步而設(shè)計(jì)。

  • 創(chuàng)建操作符justfromIterablerangeinterval (創(chuàng)建一個(gè)間隔發(fā)出的序列,用于模擬實(shí)時(shí)流)。
  • 轉(zhuǎn)換操作符map (同步轉(zhuǎn)換), flatMap (異步轉(zhuǎn)換,返回另一個(gè) Mono/Flux), concatMap (保證順序的 flatMap)。
  • 過(guò)濾操作符filtertake (取前N個(gè)), skip。
  • 組合操作符zip (將多個(gè)流合并為一個(gè)元組流), mergeconcat。
  • 錯(cuò)誤處理操作符onErrorReturn (出錯(cuò)時(shí)返回默認(rèn)值), onErrorResume (出錯(cuò)時(shí)切換到備選流), retry。

示例:使用操作符

userRepository.findAll()
    .filter(user -> user.getAge() > 18) // 過(guò)濾
    .map(User::getName)                 // 轉(zhuǎn)換:User -> String
    .flatMap(name -> {
        // 假設(shè)這是一個(gè)異步調(diào)用,返回Mono<String>
        return someAsyncService.generateGreeting(name);
    })
    .take(5)                           // 只取前5個(gè)問(wèn)候語(yǔ)
    .onErrorResume(e -> {
        // 出錯(cuò)時(shí),返回一個(gè)備用的流
        return Mono.just("Hello, Fallback User!");
    })
    .subscribe(System.out::println);   // 訂閱并消費(fèi)

第三部分:Spring WebFlux 詳解

1. 什么是 WebFlux?

Spring WebFlux 是 Spring Framework 5.0 引入的全新的、非阻塞的響應(yīng)式 Web 框架。它允許你構(gòu)建運(yùn)行在非阻塞服務(wù)器(如 Netty、Undertow、Servlet 3.1+ 容器)上的 Web 應(yīng)用,并且從底層到頂層都是響應(yīng)式的。

2. 與傳統(tǒng) Spring MVC 的對(duì)比

特性Spring MVC (Imperative)Spring WebFlux (Reactive)
編程模型同步、阻塞異步、非阻塞
并發(fā)模型每個(gè)請(qǐng)求一個(gè)線程 (Thread-per-request)少量線程處理所有請(qǐng)求 (Event-loop)
核心類型HttpServletRequestHttpServletResponseServerHttpRequestServerHttpResponse
返回值ObjectResponseEntity<T>String (視圖)Mono<T>Flux<T>ServerResponse
I/O 模型阻塞式 I/O (Blocking I/O)非阻塞式 I/O (Non-blocking I/O)
服務(wù)器Tomcat, Jetty (Servlet 容器)Netty (默認(rèn)), Undertow, Tomcat (Servlet 3.1+)
適用場(chǎng)景傳統(tǒng) CRUD,同步處理高并發(fā)、流式數(shù)據(jù)、實(shí)時(shí)應(yīng)用(如聊天、行情推送)

重要:WebFlux 并不是 Spring MVC 的替代品,而是一個(gè)并行的選擇。

3. WebFlux 的兩種編程風(fēng)格

WebFlux 支持兩種方式來(lái)編寫響應(yīng)式控制器:

  • 注解控制器 (Annotation-based Controllers):與 Spring MVC 寫法非常相似,易于上手。
@RestController
@RequestMapping("/users")
public class UserController {
    @GetMapping("/{id}")
    public Mono<User> getUserById(@PathVariable Long id) {
        // userRepository.findById 返回 Mono<User>
        return userRepository.findById(id);
    }
    @GetMapping
    public Flux<User> getAllUsers() {
        // userRepository.findAll 返回 Flux<User>
        return userRepository.findAll();
    }
    @PostMapping
    public Mono<User> createUser(@RequestBody Mono<User> userMono) {
        // 參數(shù)也可以是 Mono,直接操作流
        return userMono.flatMap(userRepository::save);
    }
}
  • 函數(shù)式端點(diǎn) (Functional Endpoints):基于 Lambda 和函數(shù)式編程,提供更細(xì)粒度的控制,路由和 handler 分離。
@Configuration
public class RoutingConfiguration {
    @Bean
    public RouterFunction<ServerResponse> routerFunction(UserHandler userHandler) {
        return RouterFunctions.route()
            .GET("/users/{id}", RequestPredicates.accept(MediaType.APPLICATION_JSON), userHandler::getUserById)
            .GET("/users", userHandler::getAllUsers)
            .POST("/users", userHandler::createUser)
            .build();
    }
}
@Component
public class UserHandler {
    public Mono<ServerResponse> getUserById(ServerRequest request) {
        Long id = Long.valueOf(request.pathVariable("id"));
        Mono<User> userMono = userRepository.findById(id);
        return ServerResponse.ok()
                .contentType(MediaType.APPLICATION_JSON)
                .body(userMono, User.class);
    }
    // ... 其他處理方法
}

4. 響應(yīng)式數(shù)據(jù)庫(kù)支持

要構(gòu)建全棧響應(yīng)式應(yīng)用,數(shù)據(jù)庫(kù)訪問(wèn)也必須是非阻塞的。Spring Data 提供了對(duì)多種 NoSQL 數(shù)據(jù)庫(kù)的響應(yīng)式支持:

  • Spring Data MongoDB Reactive
  • Spring Data Cassandra Reactive
  • Spring Data Redis Reactive
  • Spring Data R2DBC (用于關(guān)系型數(shù)據(jù)庫(kù),如 PostgreSQL, MySQL, H2 等)

示例:響應(yīng)式 MongoDB Repository

public interface ReactiveUserRepository extends ReactiveCrudRepository<User, Long> {
    Flux<User> findByAgeGreaterThan(int age);
}
// 在Controller中注入并使用
@Autowired
private ReactiveUserRepository userRepository;

第四部分:何時(shí)使用 WebFlux?

使用場(chǎng)景:

  • 高并發(fā)與高吞吐量需求:需要處理大量并發(fā)連接(如萬(wàn)級(jí)以上),且大部分是 I/O 密集型操作。
  • 實(shí)時(shí)流式應(yīng)用:需要處理持續(xù)的數(shù)據(jù)流,如股票行情、實(shí)時(shí)日志、聊天消息(SSE, WebSocket)。
  • 微服務(wù)網(wǎng)關(guān):Spring Cloud Gateway 就是基于 WebFlux 構(gòu)建的,因?yàn)樗枰咝У卮砗吐酚纱罅空?qǐng)求。

注意事項(xiàng)與挑戰(zhàn):

  • 調(diào)試難度:異步回調(diào)風(fēng)格的代碼堆棧跟蹤很長(zhǎng),問(wèn)題定位相對(duì)困難。
  • 學(xué)習(xí)曲線:需要徹底轉(zhuǎn)變同步阻塞的思維模式,理解響應(yīng)式編程概念和操作符。
  • 生態(tài)系統(tǒng):并非所有庫(kù)都提供了非阻塞的客戶端。如果你的應(yīng)用嚴(yán)重依賴一個(gè)只有阻塞式驅(qū)動(dòng)的數(shù)據(jù)庫(kù)(如 JDBC 訪問(wèn) MySQL),那么引入 WebFlux 的好處會(huì)大打折扣,因?yàn)槟阍谀硞€(gè)地方最終還是會(huì)被阻塞。
  • 不一定更快:對(duì)于低并發(fā)、CPU 密集型的場(chǎng)景,WebFlux 帶來(lái)的收益很小,甚至可能因?yàn)樯舷挛那袚Q而略有損耗。它的優(yōu)勢(shì)在于資源利用率,而不是單個(gè)請(qǐng)求的延遲。

總結(jié)

方面詳解
核心基于 Reactive Streams 規(guī)范和 Project Reactor (Mono/Flux) 庫(kù)。
目標(biāo)通過(guò)非阻塞異步方式提高系統(tǒng)資源利用率,應(yīng)對(duì)高并發(fā)場(chǎng)景。
機(jī)制背壓(Backpressure) 讓消費(fèi)者控制數(shù)據(jù)流速,避免被壓垮。
框架Spring WebFlux 提供響應(yīng)式 Web 開發(fā)支持,支持注解和函數(shù)式兩種風(fēng)格。
數(shù)據(jù)層需配合 響應(yīng)式數(shù)據(jù)庫(kù)驅(qū)動(dòng) (如 R2DBC, Reactive MongoDB) 實(shí)現(xiàn)全棧非阻塞。
選型不是萬(wàn)能藥。根據(jù)實(shí)際場(chǎng)景(高并發(fā)IO密集型、流處理)選擇,否則用 Spring MVC 更簡(jiǎn)單。

入門建議:從改造一個(gè)簡(jiǎn)單的 API 開始,將 @RestController 的返回值從 User 改為 Mono<User>,并逐步將Service和Repository層也改為返回 Mono/Flux,親身體驗(yàn)其不同。

到此這篇關(guān)于Java 響應(yīng)式編程與 Spring WebFlux的文章就介紹到這了,更多相關(guān)Java 響應(yīng)式編程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • springcloud gateway如何配置動(dòng)態(tài)路由

    springcloud gateway如何配置動(dòng)態(tài)路由

    本文主要介紹了在SpringCloudGateway中配置動(dòng)態(tài)路由的步驟,包括引入依賴、配置路由源、添加配置中心依賴、配置配置中心、定義路由規(guī)則和刷新配置等內(nèi)容,使路由規(guī)則在配置中心更新時(shí),無(wú)需重啟網(wǎng)關(guān)服務(wù)即可動(dòng)態(tài)應(yīng)用新的路由規(guī)則
    2024-10-10
  • Java刪除二叉搜索樹最大元素和最小元素的方法詳解

    Java刪除二叉搜索樹最大元素和最小元素的方法詳解

    這篇文章主要介紹了Java刪除二叉搜索樹最大元素和最小元素的方法,結(jié)合實(shí)例形式詳細(xì)分析了java針對(duì)二叉搜索樹的基本遍歷、查找、判斷、刪除等相關(guān)操作技巧,需要的朋友可以參考下
    2020-03-03
  • SpringBoot整合mybatis-plus快速入門超詳細(xì)教程

    SpringBoot整合mybatis-plus快速入門超詳細(xì)教程

    mybatis-plus 是一個(gè) Mybatis 的增強(qiáng)工具,在 Mybatis 的基礎(chǔ)上只做增強(qiáng)不做改變,為簡(jiǎn)化開發(fā)、提高效率而生,本文給大家分享SpringBoot整合mybatis-plus快速入門超詳細(xì)教程,一起看看吧
    2021-09-09
  • spring boot中使用http請(qǐng)求的示例代碼

    spring boot中使用http請(qǐng)求的示例代碼

    本篇文章主要介紹了spring boot中 使用http請(qǐng)求的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12
  • Swagger2配置Security授權(quán)認(rèn)證全過(guò)程

    Swagger2配置Security授權(quán)認(rèn)證全過(guò)程

    這篇文章主要介紹了Swagger2配置Security授權(quán)認(rèn)證全過(guò)程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Win10 Java jdk14.0.2安裝及環(huán)境變量配置詳細(xì)教程

    Win10 Java jdk14.0.2安裝及環(huán)境變量配置詳細(xì)教程

    這篇文章主要介紹了Win10 Java jdk14.0.2安裝及環(huán)境變量配置,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • java數(shù)據(jù)結(jié)構(gòu)與算法之奇偶排序算法完整示例

    java數(shù)據(jù)結(jié)構(gòu)與算法之奇偶排序算法完整示例

    這篇文章主要介紹了java數(shù)據(jù)結(jié)構(gòu)與算法之奇偶排序算法,較為詳細(xì)的分析了奇偶算法的原理并結(jié)合完整示例形式給出了實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2016-08-08
  • spring.profiles使用的方法步驟

    spring.profiles使用的方法步驟

    本文主要介紹了spring.profiles使用與spring.profiles.active和spring.profiles.include區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • Springboot實(shí)現(xiàn)Activemq死信隊(duì)列詳解

    Springboot實(shí)現(xiàn)Activemq死信隊(duì)列詳解

    這篇文章主要介紹了Springboot實(shí)現(xiàn)Activemq死信隊(duì)列詳解,Activemq服務(wù)端配置重新投遞次數(shù)超過(guò)?MaximumRedeliveries?,則會(huì)進(jìn)入死信隊(duì)列,默認(rèn)情況,有一個(gè)死信隊(duì)列:AcitveMQ.DLQ,所有的消息都投遞到此隊(duì)列,包括過(guò)期消息,重投遞失敗消息,需要的朋友可以參考下
    2023-12-12
  • 基于java配置nginx獲取真實(shí)IP代碼實(shí)例

    基于java配置nginx獲取真實(shí)IP代碼實(shí)例

    這篇文章主要介紹了基于java配置nginx獲取真實(shí)IP代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09

最新評(píng)論