一仇让、創(chuàng)建項目
這里我使用IDEA快速創(chuàng)建基于SpringBoot的工程八孝,當然你也可以選spring.io 創(chuàng)建再導入到IDEA 中欲逃。
要創(chuàng)建WebFlux 項目,必須勾選ReactiveWeb而不是傳統(tǒng)的Web 猿诸,這里為了簡化代碼使用到了Lombok婚被。
項目創(chuàng)建完后目錄:
POM 依賴,這里IDEA 自動給項目加上了spring-boot-starter-webflux梳虽。完整依賴如下:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
二址芯、編寫Controller
從序篇 可知道,編寫WebFlux 的Controller 可以沿用SpringMVC 的那一套窜觉,但是返回結果需要改成Mono或者Flux谷炸。
創(chuàng)建一個mono 接口,返回hello webflux竖螃,這里的Mono.just()方法會發(fā)射一個元素淑廊,創(chuàng)建響應式的接口就這么"簡單”。
package com.fine.webfluxquickstart.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
/**
* @author finefine at: 2019-06-01 15:02
*/
@RestController
@RequestMapping("/api/")
public class HelloController {
@GetMapping("mono")
public Mono<String> mono() {
return Mono.just("hello webflux");
}
}
那么來測試一下特咆,瀏覽器地址輸入 localhost:8080/api/mono
季惩。
其實呢,上面mono接口這種執(zhí)行模式是同步非阻塞的腻格,也就是Mono產生數(shù)據(jù)画拾,和Mono與Http 之間的訂閱消費都是在同一個線程。
那既然這樣菜职,到底是不是在同一個線程中呢青抛,更改代碼證明一下。
package com.fine.webfluxquickstart.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
/**
* @author finefine at: 2019-06-01 15:02
*/
@RestController
@RequestMapping("/api/")
@Slf4j
public class HelloController {
@GetMapping("mono")
public Mono<Object> mono() {
return Mono.create(monoSink -> {
log.info("創(chuàng)建 Mono");
monoSink.success("hello webflux");
})
.doOnSubscribe(subscription -> { //當訂閱者去訂閱發(fā)布者的時候酬核,該方法會調用
log.info("{}",subscription);
}).doOnNext(o -> { //當訂閱者收到數(shù)據(jù)時蜜另,改方法會調用
log.info("{}",o);
});
}
}
如圖,Mono的創(chuàng)建和消費都是都是在ctor-http-nio-2 這個線程中嫡意,仔細看看這log的順序举瑰,你會發(fā)現(xiàn)訂閱動作在創(chuàng)建動作之前,最后是消費蔬螟,那么為什么會這樣呢此迅?這個先留到后面講,感興趣的可以先去了解一下旧巾。
之前提到了Mono 最多發(fā)射一個數(shù)據(jù)耸序,F(xiàn)lux 可以發(fā)射多個數(shù)據(jù),那么來寫個Flux看看吧鲁猩。
package com.fine.webfluxquickstart.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;
/**
* @author finefine at: 2019-06-01 15:02
*/
@RestController
@RequestMapping("/api/")
@Slf4j
public class HelloController {
@GetMapping("mono")
public Mono<Object> mono() {
return Mono.create(monoSink -> {
log.info("創(chuàng)建 Mono");
monoSink.success("hello webflux");
})
.doOnSubscribe(subscription -> {
log.info("{}", subscription);
}).doOnNext(o -> {
log.info("{}", o);
});
}
@GetMapping("flux")
public Flux<String> flux() {
return Flux.just("hello","webflux","spring","boot");
}
}
這里Flux發(fā)射了4個數(shù)據(jù)坎怪,來看下結果:
三、總結
WebFlux 應用中廓握,所有數(shù)據(jù)都應該以Mono芋忿、Flux的形式表示炸客,這樣才能帶來最好的性能和高吞吐量。Mono和Flux 這兩種數(shù)據(jù)模型是WebFlux的核心戈钢,本片入門教程只是簡單的展示了WebFlux項目的搭建編寫侵续,要學好WebFlux 還需要掌握Reactor(Mono彪蓬、Flux)烙样,其實Reactor 和 Stream 的很多操作都有類似功能播赁,如果你對Java8Stream非常熟悉的話,學習Reactor應該是也是件容易的事情薪铜,如果還不掌握Stream 建議先去學好Stream众弓。
QQ群:577715614
源碼