spring-webflux簡(jiǎn)介與示例

簡(jiǎn)介

Spring WebFlux是Spring Framework 5.0中引入的新的反應(yīng)式Web框架。與Spring MVC不同兔跌,它不需要Servlet API,完全異步和非阻塞,并通過(guò)Reactor項(xiàng)目實(shí)現(xiàn)Reactive Streams規(guī)范贴届。并且可以在諸如Netty劲够,Undertow和Servlet 3.1+容器的服務(wù)器上運(yùn)行震桶。

Reactor中的Mono和Flux

Flux 和 Mono 是 Reactor 中的兩個(gè)基本概念。Flux 表示的是包含 0 到 N 個(gè)元素的異步序列征绎。
在該序列中可以包含三種不同類型的消息通知:正常的包含元素的消息蹲姐、序列結(jié)束的消息和序列出錯(cuò)的消息。
當(dāng)消息通知產(chǎn)生時(shí)人柿,訂閱者中對(duì)應(yīng)的方法 onNext(), onComplete()和 onError()會(huì)被調(diào)用柴墩。Mono 表示的是包含 0 或者 1 個(gè)元素的異步序列。
該序列中同樣可以包含與 Flux 相同的三種類型的消息通知凫岖。Flux 和 Mono 之間可以進(jìn)行轉(zhuǎn)換江咳。
對(duì)一個(gè) Flux 序列進(jìn)行計(jì)數(shù)操作,得到的結(jié)果是一個(gè) Mono<Long>對(duì)象哥放。把兩個(gè) Mono 序列合并在一起歼指,得到的是一個(gè) Flux 對(duì)象爹土。 了解更多

WebFlux的使用方式

圖片簡(jiǎn)介

如圖所示,WebFlux支持兩種編程方式

  • 基于SpringMvc注解@Controller
  • 基于Java8 lambda樣式路由和處理

使用WebFlux需要單獨(dú)引用它的依賴,我使用的springboot,依賴如下:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!--reactor的測(cè)試依賴-->
<dependency>
    <groupId>io.projectreactor</groupId>
    <artifactId>reactor-test</artifactId>
    <scope>test</scope>
</dependency>

示例

  • 基于SpringMvc注解

    與使用SpringMvc不同的是使用SpringWebFlux同一使用Mono<>,Flux<>對(duì)象同意返回?cái)?shù)據(jù)踩身,如下

    @RestController
    @RequestMapping("/api/user")
    public class WebFluxController {
    
        private Map<Long,User> map = new HashMap<Long,User>(10);
        @PostConstruct
        public void init(){
            map.put(1L,new User(1,"admin","admin"));
            map.put(2L,new User(1,"admin2","admin2"));
            map.put(3L,new User(1,"admin3","admin3"));
        }
        @GetMapping("/getAll")
        public Flux<User> getAllUser(){
            return Flux.fromIterable(map.entrySet().stream().map(Map.Entry::getValue)
                    .collect(Collectors.toList()));
        }
        @GetMapping("/{id}")
        public Mono<User> getUserById(@PathVariable("id") Long id){
            return Mono.just(map.get(id));
        }
        @PostMapping("/save")
        public Mono<ResponseEntity<String>> save(@RequestBody User user){
            map.put(user.getUid(),user);
            return Mono.just(new ResponseEntity<>("添加成功", HttpStatus.CREATED));
        }
    }
    

    具體實(shí)現(xiàn)代碼可查看springboot-webflux

  • 基于功能

    處理請(qǐng)求的類胀茵,實(shí)現(xiàn)具體的業(yè)務(wù)邏輯,接口 ServerRequest 表示的是一個(gè) HTTP 請(qǐng)求體挟阻。通過(guò)ServerRequest 對(duì)象可獲取到請(qǐng)求的相關(guān)信息宰掉,如請(qǐng)求路徑、查詢參數(shù)和請(qǐng)求內(nèi)容等赁濒。方法 的返回值是一個(gè) Mono<T extends ServerResponse>對(duì)象轨奄。接口 ServerResponse 用來(lái)表示 HTTP 響應(yīng)。ServerResponse 中包含了很多靜態(tài)方法來(lái)創(chuàng)建不同 HTTP 狀態(tài)碼的響應(yīng)對(duì)象

    @Component
    public class UserHandler {
    
        private IUserService userService;
        @Autowired
        public UserHandler(IUserService userService) {
            this.userService = userService;
        }
    
        public Mono<ServerResponse> getAllUser(ServerRequest serverRequest){
            Flux<User> allUser = userService.getAllUser();
            return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(allUser,User.class);
        }
    
        public Mono<ServerResponse> getUserById(ServerRequest serverRequest){
            //獲取url上的id
            Long uid = Long.valueOf(serverRequest.pathVariable("id"));
            Mono<User> user = userService.getUserById(uid);
            return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(user,User.class);
        }
    
        public Mono<ServerResponse> saveUser(ServerRequest serverRequest){
            Mono<User> user = serverRequest.bodyToMono(User.class);
            return ServerResponse.ok().build(userService.saveUser(user));
        }
    
    }
    

    為Handler類添加路由信息拒炎,

    
    @Configuration
    public class RoutingConfiguration {
    
        @Bean
        public RouterFunction<ServerResponse> monoRouterFunction(UserHandler userHandler){
            return route(GET("/api/user").and(accept(MediaType.APPLICATION_JSON)),userHandler::getAllUser)
                    .andRoute(GET("/api/user/{id}").and(accept(MediaType.APPLICATION_JSON)),userHandler::getUserById)
                    .andRoute(POST("/api/save").and(accept(MediaType.APPLICATION_JSON)),userHandler::saveUser);
        }
    
    }
    

    具體實(shí)現(xiàn)代碼可查看springboot-webflux-functional

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末挪拟,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子击你,更是在濱河造成了極大的恐慌玉组,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,639評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件丁侄,死亡現(xiàn)場(chǎng)離奇詭異惯雳,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)鸿摇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門石景,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人拙吉,你說(shuō)我怎么就攤上這事潮孽。” “怎么了筷黔?”我有些...
    開封第一講書人閱讀 157,221評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵往史,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我佛舱,道長(zhǎng)椎例,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,474評(píng)論 1 283
  • 正文 為了忘掉前任请祖,我火速辦了婚禮订歪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘损拢。我一直安慰自己陌粹,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評(píng)論 6 386
  • 文/花漫 我一把揭開白布福压。 她就那樣靜靜地躺著掏秩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪荆姆。 梳的紋絲不亂的頭發(fā)上蒙幻,一...
    開封第一講書人閱讀 49,816評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音胆筒,去河邊找鬼邮破。 笑死,一個(gè)胖子當(dāng)著我的面吹牛仆救,可吹牛的內(nèi)容都是我干的抒和。 我是一名探鬼主播,決...
    沈念sama閱讀 38,957評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼彤蔽,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼摧莽!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起顿痪,我...
    開封第一講書人閱讀 37,718評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤镊辕,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后蚁袭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體征懈,經(jīng)...
    沈念sama閱讀 44,176評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評(píng)論 2 327
  • 正文 我和宋清朗相戀三年揩悄,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了卖哎。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,646評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡删性,死狀恐怖棉饶,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情镇匀,我是刑警寧澤照藻,帶...
    沈念sama閱讀 34,322評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站汗侵,受9級(jí)特大地震影響幸缕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜晰韵,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評(píng)論 3 313
  • 文/蒙蒙 一发乔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧雪猪,春花似錦栏尚、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)抬虽。三九已至,卻和暖如春纵菌,著一層夾襖步出監(jiān)牢的瞬間阐污,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工咱圆, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留笛辟,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,358評(píng)論 2 360
  • 正文 我出身青樓序苏,卻偏偏與公主長(zhǎng)得像手幢,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子忱详,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容