快速上手WebFlux

作者: litesky | 来源:发表于2019-06-01 17:41 被阅读0次

    一、创建项目

    这里我使用IDEA快速创建基于SpringBoot的工程,当然你也可以选spring.io 创建再导入到IDEA 中。

    要创建WebFlux 项目,必须勾选ReactiveWeb而不是传统的Web ,这里为了简化代码使用到了Lombok。

    image-20190601143817483

    项目创建完后目录:

    image-20190601145307937

    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。

    创建一个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

    image-20190601154255193

    其实呢,上面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
    源码

    相关文章

      网友评论

        本文标题:快速上手WebFlux

        本文链接:https://www.haomeiwen.com/subject/yrvatctx.html