Reactor

  Reactor是基于Reactor-Stream实现反应式编程范例,一种面向数据流并传播事件的异步编程范式,也可以是同步;reactor-core包提供的核心类主要是:

Mono: 产生和处理0或1个事件
Flux:产生和处理0,,,N个事件

Mono静态方法创建

empty():创建一个不包含任何元素,只发布结束消息的序列

Mono.empty().subscribe(System.out::println);

just():可以指定序列中包含的全部元素。创建出来的 Mono序列在发布这些元素之后会自动结束。

 Mono.just("foo").subscribe(System.out::println);

justOrEmpty():从一个 Optional 对象或可能为 null 的对象中创建 Mono。只有 Optional 对象中包含值或对象不为 null 时,Mono 序列才产生对应的元素。

Mono.justOrEmpty(null).subscribe(System.out::println);

error(Throwable error):创建一个只包含错误消息的序列

Mono.error(new RuntimeException("error")).subscribe(System.out::println, System.err::println);

never():创建一个不包含任何消息通知的序列

Mono.never().subscribe(System.out::println);

fromCallable()、fromCompletionStage()、fromFuture()、fromRunnable()和 fromSupplier():分别从 Callable、CompletionStage、CompletableFuture、Runnable 和 Supplier 中创建 Mono

        //通过fromCallable创建
        Mono.fromCallable(() -> "callable run ").subscribe(System.out::println);
        //通过fromSupplier创建
        Mono.fromSupplier(() -> "create from supplier").subscribe(System.out::println);

Mono动态方法创建

通过 create()方法来使用 MonoSink 来创建 Mono。
Mono.create(sink->sink.success("create mono")).subscribe(System.out::println);

create操作符

    @Test
    public void testFlux() {
        Flux<Integer> flux = Flux.create(new Consumer<FluxSink<Integer>>() {
            @Override
            public void accept(FluxSink<Integer> fluxSink) {
                fluxSink.next(1);
                fluxSink.next(2);
                fluxSink.complete();
                fluxSink.next(3);
            }
        });

        Subscriber<Integer> subscriber = new Subscriber<Integer>() {

            @Override
            public void onSubscribe(Subscription subscription) {
                subscription.request(Integer.MAX_VALUE);
            }

            @Override
            public void onNext(Integer integer) {
                log.info("消费:{}", integer);
            }

            @Override
            public void onError(Throwable throwable) {
                log.info("异常:{}", throwable.getMessage());
            }

            @Override
            public void onComplete() {
                log.info("完成");
            }
        };
        flux.subscribe(subscriber);
    }

  把被观察者比作上游流水线(也可以比作生产者);观察者比作下游流水线(消费者)

        

  • fluxSink 就是发射器,可以发生N个事件,通过next() 完成
  • 当fluxSink发射complete()或error()事件之后,fluxSink继续发生next()事件,但是下游流水线接受complete/error事件之后,停止接受任何事件;
  • 下游接受到事件之后,进入onNext()方法;完成进入onComplete()方法,错误onError()方法
  • 上游可以不发射complete()和error() 方法,管道处于监控状态,不会执行下游onComplete()方法;

just操作符

Flux.just("1", "2", "3").subscribe(new Subscriber<String>() {
            @Override
            public void onSubscribe(Subscription subscription) {
                subscription.request(Integer.MAX_VALUE);
            }

            @Override
            public void onNext(String s) {
                log.info("元素:{}", s);
            }

            @Override
            public void onError(Throwable throwable) {
                log.error("异常:{}", throwable.getMessage());
            }

            @Override
            public void onComplete() {
                log.info("完成");
            }
        });

  just 相当特殊数组,特殊数组可以同时存放,不同类型的数据

just和create区别:
  create:根据需求手动创建事件并发送;
  just: 将已有的数据交给Flux发送,发送完成之后会自定发送complete事件;

From 系列操作符

  • fromStream: 放入jdk8的Stream流;
  • fromIterable:放入一个集合,所有实现了Collection集合接口的类都可以放入,如List,Set集合;
  • fromArray:放入一个数组;他和just区别是,just可以同时放如各种数据类型的数据;
  • from: 类似发射器,更像一个回调函数,可以发生N个事件
Flux.from(new Publisher<Integer>() {
            @Override
            public void subscribe(Subscriber<? super Integer> subscriber) {
                subscriber.onNext(1);
                subscriber.onNext(1);
                subscriber.onComplete();
            }
        }).subscribe(new Subscriber<Integer>() {
            @Override
            public void onSubscribe(Subscription subscription) {
            }

            @Override
            public void onNext(Integer s) {
                log.info("元素:{}", s);
            }

            @Override
            public void onError(Throwable throwable) {
                log.error("异常:{}", throwable.getMessage());
            }

            @Override
            public void onComplete() {
                log.info("完成");
            }
        });
  • from :通过直接引入下游管道来传输数据,一旦上游流水线与下游流水线发生订阅,就把事件之间传递给下游;
  • create 是一个发射器,发送的数据,需要下游发起请求并订阅,上游才会把事件传递给下游;
  • 在onSubscribe方法中,create操作符需要调用s.request(Integer.MAX_VALUE); from才不需要这个调用
empty()/ error()/ never()
  • Flux.empty() : 发送一个complete完成事件;
  • Flux.error(Throwable error) 发射一个Throwable错误事件
  • Flux.never() 不发送事件

interval 操作符

CountDownLatch latch = new CountDownLatch(1);
 Flux.interval(Duration.ofSeconds(2),java.time.Duration.ofSeconds(3)).subscribe(new Consumer<Long>() {
      @Override
      public void accept(Long aLong) {
          System.out.println(aLong+"=="+Thread.currentThread().getName());
      }
  });
  latch.await();
  输出内容:
  0==parallel-1
  1==parallel-1

       Interval:每隔相应的时间发送一次,

       第一个参数:第一次执行的延迟时间;第二个参数:每隔多少秒发送一次事件,发送的内容是Long类型整数,从0开始;

       interval 默认是在子线程执行事件发送的

timeout 操作符

    @Test
    public void testTimeout() {
        Flux.create(new Consumer<FluxSink<Integer>>() {
            @Override
            public void accept(FluxSink<Integer> fluxSink) {
                fluxSink.next(1);
                try {
                    TimeUnit.SECONDS.sleep(3);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                fluxSink.next(3);
            }
        }).timeout(Duration.ofSeconds(2), new Publisher<Integer>() {
            @Override
            public void subscribe(Subscriber<? super Integer> subscriber) {
                subscriber.onNext(100);
            }
        }).subscribe((Consumer<Integer>) integer -> log.info("消费:{}", integer));
    }
  • timeout :在超时之后做相应的时间
    • 第一个参数:设置超时时间,设置了2秒,2秒上游没有把事件发送过来,进入timeout,发送一个2;
    • 第二个参数:超时之后会进入的操作
  • 上游一旦超时,就会丢失下面所有的事件,不会继续传给下游,之后走timeout的逻辑

defer 操作符

Flux<Integer> defer = Flux.defer(new Supplier<Publisher<Integer>>() {
            @Override
            public Publisher<Integer> get() {
                return Flux.just(new Random().nextInt(10));
            }
        });
        Subscriber<Integer> subscriber = new Subscriber<Integer>() {
            @Override
            public void onSubscribe(Subscription s) {
                s.request(3);
            }
            @Override
            public void onNext(Integer integer) {
                System.out.println("=="+integer);
            }
            @Override
            public void onError(Throwable t) {
            }
            @Override
            public void onComplete() {
            }
        };
        defer.subscribe(subscriber);
  • defer : 延迟初始化被观察者,直到上游流水线与下游流水线发生订阅后,才会创建被观察者。

delay系列操作符

CountDownLatch latch = new CountDownLatch(1);
  Flux.just("1","2","3").delayElements(Duration.ofSeconds(2)).subscribe(new Consumer<String>() {
      @Override
      public void accept(String s) {
          System.out.println(Thread.currentThread().getName()+"=="+s);
      }
  });
  latch.await();
  输出结果:
  parallel-1==1
  parallel-2==2
  parallel-3==3
  • delayElements: 每一个原始事件都会延迟2秒,才发送,知道发送完成
  • 默认在子线程中完整

 Map操作

@Test
    public void testMap() {
        List<User> userList = new ArrayList();
        User user = new User();
        user.setName("jim");
        user.setAge(10);
        userList.add(user);
        List<String> userInfo = Flux.fromIterable(userList).map(us -> {
            StringBuffer buffer = new StringBuffer(us.getName());
            buffer.append("-");
            buffer.append(us.getAge());
            return buffer.toString();
        }).collectList().block();
        log.info("{}", userInfo);
    }

FlatMap操作符

List<User> userList = new ArrayList();
        User user = new User();
        user.setName("anthony");
        user.setAge(10);
        userList.add(user);
        Flux.fromIterable(userList).flatMap(new Function<User, Publisher<Set<Character>>>() {
            @Override
            public Publisher<Set<Character>> apply(User us) {
                char[] chars = us.getName().toCharArray();
                Set<Character> phones = new HashSet<>();
                for (char aChar : chars) {
                    phones.add(aChar);
                }
                return Flux.just(phones);
            }
        }).subscribe(new Consumer<Set<Character>>() {
            @Override
            public void accept(Set<Character> characters) {
                System.out.println(characters.toString());
            }
        });

flatmap 和map使用类型,map返回一个具体对象类型,flatmap更加灵感,返回一个新的被观察者

mergeWith 

  • 将一个事件插入到原来的事件中;
  • 类似于将List集合中插入一条数据,但是插入在List集合的末尾
  • 和zipwith不同的是,他不与源事件合并,而是插入新的事件;

reduce:

将所有数据聚合在一起之后,在传给下游流水线,最后只传递了一个事件给下游

 Flux.just(1, 2, 3, 4, 5).reduce(new BiFunction<Integer, Integer, Integer>() {
            @Override
            public Integer apply(Integer param1, Integer param2) {
                log.info("{}加上{}", param1, param2);
                return param1 + param2;
            }
        }).subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) {
                log.info("结果:{}", integer);
            }
        });

buffer

buffer 就将单个数据分组聚合,3就是几个事件合并为一个组,然后发送出去的是一个List集合;如果最后的数据撮不成3了,就使用余数存放到一个List集合进行发送

Flux.just(1, 2, 3, 4, 5, 6, 7).buffer(3).subscribe(new Consumer<List<Integer>>() {
            @Override
            public void accept(List<Integer> integers) {
                log.info("{}", integers);
            }
        });

------------结果-----------------
 : [1, 2, 3]
 : [4, 5, 6]
 : [7]

groupBy

  • groupBy 将事件按照某种规则进行分组,同时将分组id传递给下游;分组之后传递给下游的是一个被观察者(生产者);
  • 与buffer组合发送不同,这里还是一个个事件往下传递
Flux.just(1, 2, 3, 4, 5, 6, 7, 8).groupBy(new Function<Integer, Integer>() {
            @Override
            public Integer apply(Integer integer) {
                return integer % 3;
            }
        }).subscribe(new Consumer<GroupedFlux<Integer, Integer>>() {
            @Override
            public void accept(GroupedFlux<Integer, Integer> groupedFlux) {
                groupedFlux.subscribe(new Consumer<Integer>() {
                    @Override
                    public void accept(Integer integer) {
                        log.info("分组id={},值为:{}", groupedFlux.key(), integer);
                    }
                });
            }
        });
分组id=1 ==值==1
分组id=2 ==值==2
分组id=0 ==值==3
分组id=1 ==值==4
分组id=2 ==值==5
分组id=0 ==值==6
分组id=1 ==值==7
分组id=2 ==值==8

handler

handler :在事件传递的中间环节做数据的处理,处理过程中如果产生多个新的事件,通过发射器继续将新事件往下传递

注意的是,handler对源事件进行处理之后传递一个新的事件,每次只能传递一个不能多传;

Flux.just("15", "66", "", "33").filter(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                if (StringUtils.isEmpty(s)) {
                    return false;
                }
                return true;
            }
        }).handle(new BiConsumer<String, SynchronousSink<Integer>>() {
            @Override
            public void accept(String s, SynchronousSink<Integer> integerSynchronousSink) {
                integerSynchronousSink.next(Integer.valueOf(s));
            }
        }).subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) {
                log.info("结果:{}", integer);
            }
        });

doOnNext

  • doOnNext :是事件的中间处理流程,不能改成源事件类型以及发射新的事件;
  • 即使在中间改变了传递来值,不会改变源事件中的值;
  • 如果对象引用类型,如传递UserVO对象,doOnNext对UserVO属性name修改,它传递name就会发生变化
Flux.just("15", "66", "", "33").filter(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                if (StringUtils.isEmpty(s)) {
                    return false;
                }
                return true;
            }
        }).doOnNext(new Consumer<String>() {
            @Override
            public void accept(String s) {
                log.info("{}", s);
                s = "555";
            }
        }).subscribe(new Consumer<String>() {
            @Override
            public void accept(String str) {
                log.info("结果:{}", str);
            }
        });

doOnError 使用和doOnNext相似,就是出现错误后,中间逻辑处理

doOnComplete 使用和doOnNext相似,整个事件流完成之后应该做些什么事情

retry 操作符

      retry :当处理流程中出现错误时,是否发起重试

  • 第一个参数:最大重试次数
  • 第二个参数:出现错误之后是否重试返回true:重试,false不重试
Flux.just(1, 2).handle(new BiConsumer<Integer, SynchronousSink<Integer>>() {

            @Override
            public void accept(Integer elem, SynchronousSink<Integer> integerSynchronousSink) {
                if (1 == elem) {
                    integerSynchronousSink.error(new RuntimeException("错误"));
                } else {
                    integerSynchronousSink.next(elem + 10);
                }
            }
        }).retry(2, new Predicate<Throwable>() {
            @Override
            public boolean test(Throwable throwable) {
                log.info("重试:{}", throwable.getMessage());
                if (throwable instanceof RuntimeException) {
                    log.info("异常:{}", throwable.getMessage());
                }
                return false;
            }
        }).onErrorResume(new Function<Throwable, Publisher<Integer>>() {

            @Override
            public Publisher<Integer> apply(Throwable throwable) {
                log.info("使用0代替");
                return Flux.just(0);
            }
        }).subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) {
                log.info("结果:{}", integer);
            }
        });

onErrorResume:在捕获到错误之后,应该做点什么错误处理的逻辑,返回的是一个发射器;这里没有做错误的逻辑处理,直接返回Flux.just(0),在项目中可以根据具体需要做处理;

posted on 2022-04-17 21:16  溪水静幽  阅读(1282)  评论(0)    收藏  举报