偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

解鎖異步響應(yīng)力量:淺析Spring WebFlux

開發(fā) 架構(gòu)
談到Spring WebFlux就需要著重解釋下響應(yīng)式編程模型,響應(yīng)式編程是一種面向數(shù)據(jù)流和變化傳播的編程范式。它倡導(dǎo)使用異步數(shù)據(jù)流來(lái)構(gòu)建事件驅(qū)動(dòng)的、可擴(kuò)展的應(yīng)用程序。

1.WebFlux簡(jiǎn)介

Spring WebFlux是Spring框架的一個(gè)模塊,用于構(gòu)建反應(yīng)式、異步和事件驅(qū)動(dòng)的應(yīng)用程序。它提供了一種基于Reactive Streams標(biāo)準(zhǔn)的編程模型,能夠處理大量并發(fā)請(qǐng)求和高吞吐量,同時(shí)具有較低的資源消耗。

傳統(tǒng)的Servlet API和Spring MVC是基于同步阻塞式編程模型的,而Spring WebFlux則是基于響應(yīng)式編程模型的,相比較下有如下優(yōu)勢(shì):

并發(fā)處理:

  • Servlet API和Spring MVC:采用同步阻塞IO模型,每個(gè)請(qǐng)求都會(huì)占用一個(gè)線程,如果有大量的長(zhǎng)時(shí)間IO操作或者并發(fā)請(qǐng)求,會(huì)導(dǎo)致線程資源耗盡。
  • Spring WebFlux:采用非阻塞IO模型,在IO操作完成前不會(huì)阻塞線程,因此能夠更高效地處理大量并發(fā)請(qǐng)求。

編程模型:

  • Servlet API和Spring MVC:基于Servlet規(guī)范,通常使用注解或者配置文件來(lái)定義控制器和URL映射。
  • Spring WebFlux:提供了注解式編程和函數(shù)式編程兩種風(fēng)格的路由定義方式,使得開發(fā)者可以選擇更適合自己項(xiàng)目的方式進(jìn)行開發(fā)。

線程模型:

  • Servlet API和Spring MVC:每個(gè)請(qǐng)求需要綁定一個(gè)線程,線程池負(fù)責(zé)管理這些線程。
  • Spring WebFlux:基于事件驅(qū)動(dòng)和響應(yīng)式流,不需要為每個(gè)請(qǐng)求分配獨(dú)立線程,能夠更有效地利用系統(tǒng)資源。

應(yīng)用場(chǎng)景:

  • Servlet API和Spring MVC:更適合傳統(tǒng)的同步IO應(yīng)用,如CRUD操作等。
  • Spring WebFlux:適合處理I/O密集型應(yīng)用,如服務(wù)器推送事件、WebSocket通信以及需要處理大量并發(fā)請(qǐng)求的場(chǎng)景。

2.響應(yīng)式編程

談到Spring WebFlux就需要著重解釋下響應(yīng)式編程模型,響應(yīng)式編程是一種面向數(shù)據(jù)流和變化傳播的編程范式。它倡導(dǎo)使用異步數(shù)據(jù)流來(lái)構(gòu)建事件驅(qū)動(dòng)的、可擴(kuò)展的應(yīng)用程序。在響應(yīng)式編程中,數(shù)據(jù)和事件以流的形式進(jìn)行處理,并且整個(gè)系統(tǒng)會(huì)對(duì)這些流式數(shù)據(jù)進(jìn)行監(jiān)聽和響應(yīng)。主要優(yōu)勢(shì)如下:

  • 異步和非阻塞:響應(yīng)式編程采用異步編程模型,能夠更高效地利用系統(tǒng)資源,同時(shí)避免線程阻塞,提高系統(tǒng)的并發(fā)處理能力。
  • 事件驅(qū)動(dòng):通過訂閱數(shù)據(jù)流和事件,系統(tǒng)能夠更靈活地響應(yīng)外部輸入,適合處理實(shí)時(shí)性要求高的場(chǎng)景。
  • 可擴(kuò)展性:采用反應(yīng)式編程模型可以輕松地構(gòu)建可擴(kuò)展的系統(tǒng),因?yàn)樗鼜?qiáng)調(diào)組件間的解耦和消息傳遞。
  • 簡(jiǎn)潔清晰:響應(yīng)式編程模型通常使用函數(shù)式風(fēng)格,代碼更加簡(jiǎn)潔清晰,易于理解和維護(hù)。

舉個(gè)例子:

假設(shè)我們需要實(shí)時(shí)獲取多個(gè)城市的天氣數(shù)據(jù)并展示給用戶,這就涉及到了異步獲取數(shù)據(jù)和實(shí)時(shí)推送數(shù)據(jù)給前端的需求。

在傳統(tǒng)的同步編程模型中,如果我們采用每個(gè)城市一個(gè)線程的方式來(lái)獲取天氣數(shù)據(jù),可能會(huì)因?yàn)榫W(wǎng)絡(luò)IO等待而造成大量線程阻塞,浪費(fèi)系統(tǒng)資源。而且隨著城市數(shù)量的增多,線程管理和資源利用將變得更加困難。

通過采用響應(yīng)式編程模型,我們可以將天氣數(shù)據(jù)看作一個(gè)反應(yīng)式流,通過訂閱這個(gè)數(shù)據(jù)流,可以實(shí)時(shí)地獲取各個(gè)城市的天氣信息。當(dāng)某個(gè)城市的天氣數(shù)據(jù)發(fā)生變化時(shí),系統(tǒng)能夠及時(shí)地向訂閱者發(fā)送新的數(shù)據(jù),從而實(shí)現(xiàn)實(shí)時(shí)更新。

另外,由于天氣數(shù)據(jù)的獲取和推送是異步非阻塞的,不需要為每個(gè)城市的天氣數(shù)據(jù)分配獨(dú)立的線程,能夠更高效地利用系統(tǒng)資源,提高系統(tǒng)的并發(fā)處理能力。

3.Spring WebFlux核心組件

Spring WebFlux 框架由以下核心組件組成:

(1)Handler

Handler是Spring WebFlux中用于處理請(qǐng)求的核心組件。它可以是一個(gè)函數(shù)式的處理器,也可以是一個(gè)注解式的控制器(類似于Spring MVC中的Controller)。當(dāng)接收到一個(gè)HTTP請(qǐng)求時(shí),WebFlux會(huì)根據(jù)路由規(guī)則把請(qǐng)求映射到對(duì)應(yīng)的Handler上,然后由Handler來(lái)實(shí)際處理請(qǐng)求并生成響應(yīng)。在函數(shù)式編程風(fēng)格中,Handler通常是一個(gè)處理器函數(shù),而在注解式編程中,Handler通常是一個(gè)帶有@RequestMapping注解的控制器方法。

(2)核心控制器DispatcherHandler

核心控制器DispatcherHandler等同于阻塞方式的DispatcherServlet,DispatcherHandler實(shí)現(xiàn)ApplicationContextAware,那么必然會(huì)調(diào)用setApplicationContext方法。

public class DispatcherHandler implements WebHandler, ApplicationContextAware {
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        initStrategies(applicationContext);
    }
}

initStrategies初始化

獲取HandlerMapping,HandlerAdapter,HandlerResultHandler的所有實(shí)例

protected void initStrategies(ApplicationContext context) {
    //獲取HandlerMapping及其子類型的bean
    //HandlerMapping根據(jù)請(qǐng)求request獲取handler執(zhí)行鏈
    Map<String, HandlerMapping> mappingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
            context, HandlerMapping.class, true, false);
 
    ArrayList<HandlerMapping> mappings = new ArrayList<>(mappingBeans.values());
    //排序
    AnnotationAwareOrderComparator.sort(mappings);
    this.handlerMappings = Collections.unmodifiableList(mappings);
 
    //獲取HandlerAdapter及其子類型的bean
    Map<String, HandlerAdapter> adapterBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
            context, HandlerAdapter.class, true, false);
 
    this.handlerAdapters = new ArrayList<>(adapterBeans.values());
    //排序
    AnnotationAwareOrderComparator.sort(this.handlerAdapters);
 
    //獲取HandlerResultHandler及其子類型的bean
    Map<String, HandlerResultHandler> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
            context, HandlerResultHandler.class, true, false);
 
    this.resultHandlers = new ArrayList<>(beans.values());
    AnnotationAwareOrderComparator.sort(this.resultHandlers);
}

DispatcherHandler的總體流程

  • 通過HandlerMapping(和DispatcherServlet中的HandlerMapping不同)獲取到HandlerAdapter放到ServerWebExchange的屬性中
  • 獲取到HandlerAdapter后觸發(fā)handle方法,得到HandlerResult
  • 通過HandlerResult,觸發(fā)handleResult,針對(duì)不同的返回類找到不同的HandlerResultHandler如視圖渲染ViewResolutionResultHandler、ServerResponseResultHandler、ResponseBodyResultHandler、ResponseEntityResultHandler不同容器有不同的實(shí)現(xiàn),如Reactor,Jetty,Tomcat等。

(3)Router

Router用于定義URL路由規(guī)則,將請(qǐng)求映射到對(duì)應(yīng)的Handler上。它負(fù)責(zé)根據(jù)請(qǐng)求的URL路徑和HTTP方法找到對(duì)應(yīng)的Handler,并將請(qǐng)求轉(zhuǎn)發(fā)給該Handler進(jìn)行處理。Router可以通過多種方式定義,包括函數(shù)式路由定義和注解式路由定義。在函數(shù)式編程風(fēng)格中,我們可以使用Java 8的lambda表達(dá)式和RouterFunctions來(lái)定義路由規(guī)則;而在注解式編程中,我們可以使用類似@RequestMapping和@RestController這樣的注解來(lái)定義路由規(guī)則。

(4)RouterFunction

RouterFunction是用于定義路由規(guī)則的主要接口,它可以將HTTP請(qǐng)求映射到對(duì)應(yīng)的處理函數(shù)。通過RouterFunction,我們可以根據(jù)請(qǐng)求的URL路徑和HTTP方法找到對(duì)應(yīng)的Handler,并將請(qǐng)求轉(zhuǎn)發(fā)給該Handler進(jìn)行處理。

@Configuration
public class RouterConfig {

    @Bean
    public RouterFunction<ServerResponse> helloRouterFunction(HelloHandler helloHandler) {
        return route(GET("/hello"), helloHandler::handleHello);
    }
}

在這段示例代碼中,我們首先通過@Configuration注解標(biāo)記了RouterConfig類,使其成為Spring的配置類。然后,我們使用@Bean注解定義了一個(gè)名為helloRouterFunction的Bean,它返回一個(gè)RouterFunction<ServerResponse>實(shí)例。

這里的route(GET("/hello"), helloHandler::handleHello)表示當(dāng)收到GET請(qǐng)求且路徑為"/hello"時(shí),將請(qǐng)求轉(zhuǎn)發(fā)給helloHandler的handleHello方法進(jìn)行處理。這里使用了靜態(tài)導(dǎo)入,使得可以直接調(diào)用GET方法,簡(jiǎn)化路由規(guī)則的定義。

@Component
public class HelloHandler {
    public Mono<ServerResponse> handleHello(ServerRequest request) {
        return ServerResponse.ok().bodyValue("Hello, WebFlux!");
    }
}

在HelloHandler類中,我們通過@Component注解標(biāo)記為Spring管理的組件,并編寫了handleHello方法來(lái)處理請(qǐng)求。該方法返回一個(gè)Mono<ServerResponse>,在本例中是將"Hello, WebFlux!"字符串作為響應(yīng)體返回給客戶端。

(5)WebHandler

WebHandler是處理請(qǐng)求和生成響應(yīng)的抽象接口,它充當(dāng)了請(qǐng)求和響應(yīng)對(duì)象之間的橋梁。在WebFlux中,WebHandler接口定義了handle方法,用于處理ServerHttpRequest和ServerHttpResponse對(duì)象。它提供了一種統(tǒng)一的處理機(jī)制,使得不同類型的Handler可以與請(qǐng)求-響應(yīng)生命周期進(jìn)行交互。

4.選WebFlux還是Spring MVC?

首先你需要明確一點(diǎn)就是:WebFlux不是Spring MVC的替代方案,WebFlux并不能使接口的響應(yīng)時(shí)間縮短,它僅僅能夠提升吞吐量和伸縮性 。雖然WebFlux也可以被運(yùn)行在Servlet容器上(需是Servlet 3.1+以上的容器),但是WebFlux

主要還是應(yīng)用在異步非阻塞編程模型,而Spring MVC是同步阻塞的,如果你目前在Spring MVC框架中大量使用非同步方案,那么,WebFlux才是你想要的,否則,使用Spring MVC才是你的首選。

在微服務(wù)架構(gòu)中,Spring MVC和WebFlux可以混合使用,比如已經(jīng)提到的,對(duì)于那些IO密集型服務(wù)(如網(wǎng)關(guān)),我們就可以使用WebFlux來(lái)實(shí)現(xiàn)。


從上圖中,可以一眼看出Spring MVC和Spring WebFlux的相同點(diǎn)和不同點(diǎn):

相同點(diǎn):

  • 都可以使用Spring MVC注解,如@Controller,方便我們?cè)趦蓚€(gè)Web框架中自由轉(zhuǎn)換;
  • 均可以使用Tomcat,Jetty,Undertow Servlet容器(Servlet 3.1+);
  • ...

不同點(diǎn):

  • Spring MVC因?yàn)槭鞘褂玫耐阶枞?,更方便開發(fā)人員編寫功能代碼,Debug測(cè)試等,一般來(lái)說(shuō),如果Spring MVC能夠滿足的場(chǎng)景,就盡量不要用WebFlux;
  • WebFlux默認(rèn)情況下使用Netty作為服務(wù)器;
  • WebFlux不支持MySql;

5.WebFlux與Spring框架集成

pom.xml:

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>webflux-demo</artifactId>
    <version>1.0.0</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.3</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
    </dependencies>
</project>

在上述配置中,我們使用了Spring Boot的起步依賴
spring-boot-starter-webflux來(lái)引入WebFlux相關(guān)的依賴。接下來(lái),我們將創(chuàng)建一個(gè)簡(jiǎn)單的Controller并將其拆分到單獨(dú)的類中。

首先,創(chuàng)建一個(gè)名為 HelloController 的類:

import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.function.server.ServerRequest;
import reactor.core.publisher.Mono;

import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;

public class HelloController {
    public RouterFunction<ServerResponse> route() {
        return route(GET("/hello"), this::handleHello);
    }

    private Mono<ServerResponse> handleHello(ServerRequest request) {
        return ServerResponse.ok().bodyValue("Hello, WebFlux!");
    }
}

然后在主應(yīng)用程序中注入HelloController:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;

@SpringBootApplication
public class WebFluxIntegrationDemo {

    public static void main(String[] args) {
        SpringApplication.run(WebFluxIntegrationDemo.class, args);
    }

    @Bean
    public RouterFunction<ServerResponse> monoRouterFunction(HelloController helloController) {
        return helloController.route();
    }
}

在這個(gè)示例中,我們通過@Bean注解將HelloController注入到主應(yīng)用程序中,并且調(diào)用其route方法來(lái)定義路由規(guī)則。

6.總結(jié)

關(guān)于pring WebFlux 很多很多,本文主要總結(jié)如下幾點(diǎn)

優(yōu)點(diǎn):

  • 非阻塞和異步:能夠處理大量并發(fā)請(qǐng)求,提高系統(tǒng)的吞吐量。
  • 響應(yīng)式編程模型:支持響應(yīng)式數(shù)據(jù)流處理,適合處理實(shí)時(shí)、事件驅(qū)動(dòng)的應(yīng)用場(chǎng)景。
  • 彈性和擴(kuò)展性:能夠輕松地與反應(yīng)式數(shù)據(jù)流、異步數(shù)據(jù)庫(kù)等集成,方便構(gòu)建彈性和可擴(kuò)展的系統(tǒng)。

缺點(diǎn):

  • 學(xué)習(xí)曲線較陡峭:相對(duì)于傳統(tǒng)的Servlet編程模型,對(duì)于開發(fā)人員需要一定的學(xué)習(xí)成本。
  • 對(duì)某些傳統(tǒng)的基于Servlet的庫(kù)和框架的兼容性可能不夠理想。

適用范圍:

  • 需要處理高并發(fā)、實(shí)時(shí)性要求高的網(wǎng)絡(luò)應(yīng)用程序;
  • 適合微服務(wù)架構(gòu)和需要異步通信的項(xiàng)目;
  • 處理大規(guī)模數(shù)據(jù)流和事件驅(qū)動(dòng)的應(yīng)用場(chǎng)景。
責(zé)任編輯:姜華 來(lái)源: 今日頭條
相關(guān)推薦

2021-06-02 10:39:59

ServletWebFluxSpringMVC

2024-09-29 13:53:58

數(shù)據(jù)飛輪數(shù)據(jù)中臺(tái)數(shù)字化轉(zhuǎn)型

2010-04-14 14:14:42

Oracle用戶解鎖

2022-07-04 09:15:10

Spring請(qǐng)求處理流程

2023-02-09 08:01:12

核心組件非阻塞

2023-09-04 11:52:53

SpringMVC性能

2017-11-06 08:28:44

DDD架構(gòu)設(shè)計(jì)IT

2022-11-04 08:39:46

SpringWebFlux

2024-06-13 00:54:19

2021-07-28 20:13:04

響應(yīng)式編程

2024-09-29 18:49:39

2009-08-17 13:34:02

C#異步操作

2023-11-02 18:01:24

SpringMVC配置

2020-03-24 09:54:57

SpringMVCWebFlux

2009-07-28 16:40:11

ASP.NET異步頁(yè)面

2021-07-15 11:16:31

Spring WebWebFlux架構(gòu)

2022-09-26 08:54:39

Spring函數(shù)式編程

2019-03-04 08:48:23

Spring WebFJavaIO

2020-07-07 07:00:00

Spring WebFREST APIReactive AP

2025-07-24 00:45:00

AIMCP服務(wù)端
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)