一、创建项目
这里我使用IDEA快速创建基于SpringBoot的工程,当然你也可以选spring.io 创建再导入到IDEA 中。
要创建WebFlux 项目,必须勾选ReactiveWeb而不是传统的Web ,这里为了简化代码使用到了Lombok。
image-20190601143817483项目创建完后目录:
image-20190601145307937POM 依赖,这里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。
创建一个mono 接口,返回hello webflux,这里的Mono.just()方法会发射一个元素,创建响应式的接口就这么"简单”。
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接口这种执行模式是同步非阻塞的,也就是Mono产生数据,和Mono与Http 之间的订阅消费都是在同一个线程。
image.png那既然这样,到底是不是在同一个线程中呢,更改代码证明一下。
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("创建 Mono");
monoSink.success("hello webflux");
})
.doOnSubscribe(subscription -> { //当订阅者去订阅发布者的时候,该方法会调用
log.info("{}",subscription);
}).doOnNext(o -> { //当订阅者收到数据时,改方法会调用
log.info("{}",o);
});
}
}
如图,Mono的创建和消费都是都是在ctor-http-nio-2 这个线程中,仔细看看这log的顺序,你会发现订阅动作在创建动作之前,最后是消费,那么为什么会这样呢?这个先留到后面讲,感兴趣的可以先去了解一下。
image-20190601170432212之前提到了Mono 最多发射一个数据,Flux 可以发射多个数据,那么来写个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("创建 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发射了4个数据,来看下结果:
image-20190601172604363三、总结
WebFlux 应用中,所有数据都应该以Mono、Flux的形式表示,这样才能带来最好的性能和高吞吐量。Mono和Flux 这两种数据模型是WebFlux的核心,本片入门教程只是简单的展示了WebFlux项目的搭建编写,要学好WebFlux 还需要掌握Reactor(Mono、Flux),其实Reactor 和 Stream 的很多操作都有类似功能,如果你对Java8Stream非常熟悉的话,学习Reactor应该是也是件容易的事情,如果还不掌握Stream 建议先去学好Stream。
QQ群:577715614
源码
网友评论