WebFlux是一個基于反應(yīng)式編程模型的Web框架,它提供了一種處理高并發(fā)和高吞吐量的Web應(yīng)用程序的解決方案。本文將介紹WebFlux的概念、反應(yīng)式編程的核心API和編程模型,并探討學(xué)習(xí)WebFlux的重要性。
WebFlux是什么?
WebFlux是Spring5添加的一個新模塊,是一個使用響應(yīng)式編程和異步非阻塞的Web開發(fā)框架,它的功能和Spring MVC類似,但是它可以更好地利用多核處理器和高并發(fā)連接,提高系統(tǒng)的吞吐量和伸縮性。它完全無阻塞,支持反應(yīng)流反向壓力,可在 Netty、Undertow 和 Servlet 3.1+ 容器等服務(wù)器上運行。核心是基于Reactor的相關(guān)API實現(xiàn)的。
什么是反應(yīng)式編程?
- 反應(yīng)式一詞指的是圍繞對變化做出反應(yīng)而構(gòu)建的編程模型,如網(wǎng)絡(luò)組件對 I/O 事件做出反應(yīng)、用戶界面控制器對鼠標(biāo)事件做出反應(yīng)等。從這個意義上說,非阻塞就是反應(yīng)式,因為我們現(xiàn)在的模式是在操作完成或數(shù)據(jù)可用時對通知做出反應(yīng),而不是被阻塞。
- 同時反應(yīng)式與非阻塞反向壓力建立了聯(lián)系。在同步的命令式代碼中,阻塞調(diào)用是一種自然的反向壓力,它迫使調(diào)用者等待。而在非阻塞代碼中,控制事件的速度就變得非常重要,這樣快速的生產(chǎn)者就不會壓倒其消費者(目的地)。
- 反應(yīng)流(Reactive Streams)是一種規(guī)范(Java 9 也采用了這種規(guī)范),它定義了異步組件與反向壓力之間的交互。例如,數(shù)據(jù)存儲庫(作為發(fā)布者)可以生成數(shù)據(jù),然后 HTTP 服務(wù)器(作為訂閱者)可以將數(shù)據(jù)寫入響應(yīng)。反應(yīng)流的主要目的是讓訂閱者控制發(fā)布者生成數(shù)據(jù)的快慢。
WebFlux是如何實現(xiàn)響應(yīng)式編程的?
- WebFlux是基于Reactor庫的,Reactor是一個實現(xiàn)了響應(yīng)式流規(guī)范的Java庫,它提供了Flux和Mono兩種類型的數(shù)據(jù)流,分別表示多個和單個的異步數(shù)據(jù)源。WebFlux使用Flux和Mono來處理Web請求和響應(yīng),以及與數(shù)據(jù)庫和其他服務(wù)的交互,從而實現(xiàn)了端到端的異步非阻塞的處理流程。
- WebFlux支持兩種編程模式,一種是基于注解的,類似于Spring MVC,使用?
@Controller
?和?@RequestMapping
?等注解來定義控制器和路由;另一種是基于函數(shù)式的,使用?RouterFunction
?和?HandlerFunction
?來編寫更靈活和函數(shù)式的代碼。
WebFlux有什么優(yōu)勢和局限性?
- WebFlux的主要優(yōu)勢是可以提高Web應(yīng)用的性能和效率,特別是在IO密集型和高并發(fā)的場景下,WebFlux可以使用更少的線程和資源來處理更多的請求,從而減少延遲和內(nèi)存占用。WebFlux也可以更好地適應(yīng)微服務(wù)和云原生的架構(gòu),因為它可以更容易地實現(xiàn)服務(wù)間的異步通信和流式處理。
- WebFlux的主要局限性是它需要使用響應(yīng)式編程的思維和技巧來編寫和理解代碼,這對于習(xí)慣了同步阻塞編程的開發(fā)者來說可能有一定的學(xué)習(xí)曲線和挑戰(zhàn)。WebFlux也需要與其他支持響應(yīng)式編程的庫和框架配合使用,例如Reactor,RxJava,Spring Data Reactive等,否則可能會出現(xiàn)阻塞或不兼容的問題。
應(yīng)用示例
環(huán)境配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
注意: 不要再引spring-boot-starter-web包,否則默認(rèn)還是使用的Servlet棧
基于注解
@RestController
@RequestMapping("/demos")
public class DemoController {
private static final Logger logger = LoggerFactory.getLogger(DemoController.class);
@GetMapping("/index")
public Mono<String> index() {
logger.info("start {}, {}", Thread.currentThread().getName(), System.currentTimeMillis()) ;
// 這里是我們需要返回的值,在Servlet棧中直接返回具體的值,但在WebFlux中需要用Mono或Flux將數(shù)據(jù)進(jìn)行包裝
Mono<String> result = Mono.just(666) ;
logger.info("end {}, {}", Thread.currentThread().getName(), System.currentTimeMillis()) ;
return result;
}
}
基于注解的方式處理返回值不一樣外其它與傳統(tǒng)的WebMVC一樣。
基于函數(shù)式
@Bean
public RouterFunction<ServerResponse> router1() {
return RouterFunctions.route()
.GET("/r1", request -> {
String id = request.queryParam("id").orElse(null) ;
if ("2".equals(id)) {
throw new RuntimeException("Router Param id Error...") ;
}
return ServerResponse.ok().bodyValue("你輸入的是id = " + id) ;
}).build() ;
}
函數(shù)式,我們只需像定義普通的bean一樣即可,返回值為?RouterFucntion<ServerResponse>
?。
HandlerFunction
? 處理:該函數(shù)接收 ?ServerRequest
? 并返回延遲的 ?ServerResponse
?(即 ?Mono<ServerResponse>
?)。請求和響應(yīng)對象都不可變。?HandlerFunction
? 相當(dāng)于基于注解的編程模型中 ?@RequestMapping
? 方法的主體。
總結(jié)
WebFlux作為一種新一代的Web框架,具有響應(yīng)式能力、非阻塞I/O和函數(shù)式編程風(fēng)格等優(yōu)勢。它適用于需要處理高并發(fā)和高吞吐量的應(yīng)用場景,并在微服務(wù)架構(gòu)和云原生應(yīng)用開發(fā)中表現(xiàn)出色。然而,學(xué)習(xí)和采用WebFlux可能需要一些時間和精力,并且在遷移到WebFlux時需要考慮現(xiàn)有代碼的調(diào)整和遷移工作。因此,您應(yīng)該根據(jù)您的項目需求和團隊的技術(shù)能力來決定是否值得學(xué)習(xí)和采用WebFlux。了解其特點和優(yōu)勢,并與團隊進(jìn)行討論和評估,以做出明智的決策。
如果你對編程知識和相關(guān)職業(yè)感興趣,歡迎訪問編程獅官網(wǎng)(http://m.hgci.cn/)。在編程獅,我們提供廣泛的技術(shù)教程、文章和資源,幫助你在技術(shù)領(lǐng)域不斷成長。無論你是剛剛起步還是已經(jīng)擁有多年經(jīng)驗,我們都有適合你的內(nèi)容,助你取得成功。