订阅者可以充当发布者吗?

时间:2017-12-22 06:32:17

标签: reactive-programming publish-subscribe java-9 reactive reactive-streams

就Reactive Streams而言,有一个发布者,它可以拥有尽可能多的订阅者。

但是假设订阅者从Publisher获取消息。现在,这个订阅者(比如Subs1)更改/修改消息并将其传递给其他订阅者(比如Subs2),这会消耗修改后的消息。

那么这个Subs1订户可以充当发布者,可以将消息传递给新的Subs2订户吗?

我不确定是否可能,但我认为这种情况是可能的。

如果可行,请建议一种可行的方法。

1 个答案:

答案 0 :(得分:1)

  

如果我们想要转换传入消息并将其进一步传递给下一个订阅服务器,我们需要实现处理器接口。这既可以作为订阅者,也可以作为发布者,因为它处理这些消息并发送它们进行进一步处理。

以下是执行此操作的完整实现:​​

  1. 创建一个实现处理器并扩展SubmissionPublisher的MyTransformer类,因为它将同时作为订阅者和发布者:

    import java.util.concurrent.Flow;
    import java.util.concurrent.Flow.Subscription;
    import java.util.concurrent.SubmissionPublisher;
    import java.util.function.Function;
    
    public class MyTransformer<T, R> extends SubmissionPublisher<R> implements Flow.Processor<T, R> {
    
    private Function<T, R> function;
    private Flow.Subscription subscription;
    
    public MyTransformer(Function<T, R> function) {
        super();
        this.function = function;
    }
    
    @Override
    public void onComplete() {
        System.out.println("Transformer Completed");
    }
    
    @Override
    public void onError(Throwable e) {
        e.printStackTrace();
    }
    
    @Override
    public void onNext(T item) {
        System.out.println("Transformer Got : "+item);
        submit(function.apply(item));
        subscription.request(1);
    
    }
    
    @Override
    public void onSubscribe(Subscription subscription) {
        this.subscription = subscription;
        subscription.request(1);
    }
    
    
    
    }
    
  2. 创建一个TestSubscriber类,它实现Subscriber接口并实现所需的方法:

  3. 在处理开始之前调用onSubscribe()方法。订阅的实例作为参数传递。它是一个用于控制订阅服务器和发布服务器之间消息流的类。

    这里的主要方法是onNext() - 每当Publisher发布新消息时都会调用它。

    我们正在使用实现Publisher接口的SubmissionPublisher类。

    我们将向发布者提交N个元素 - 我们的TestSubscriber将会收到这些元素。

    注意,我们在TestSubscriber的实例上调用close()方法。它将在给定Publisher的每个订阅服务器下面调用onComplete()回调。

    import java.util.LinkedList;
    import java.util.List;
    import java.util.concurrent.Flow.Subscriber;
    import java.util.concurrent.Flow.Subscription;
    
    public class TestSubscriber<T> implements Subscriber<T> {
    
        private Subscription subscription;
    
        public List<T> consumed = new LinkedList<>();
    
        @Override
        public void onComplete() {
            System.out.println("Subsciber Completed");
        }
    
        @Override
        public void onError(Throwable arg0) {
            arg0.printStackTrace();
        }
    
        @Override
        public void onNext(T item) {
            System.out.println("In Subscriber Got : "+item);
            subscription.request(1);
    
        }
    
        @Override
        public void onSubscribe(Subscription subscription) {
            this.subscription = subscription;
            subscription.request(1);
        }
    
    }
    
    1. 以下是发布服务器发布字符串元素的处理流程。
    2. MyTransformer正在将String解析为整数 - 这意味着需要在此处进行转换。

      import java.util.List;
      import java.util.concurrent.SubmissionPublisher;;
      
      public class TestTransformer {
      
          public static void main(String... args) {
              SubmissionPublisher<String> publisher = new SubmissionPublisher<>();
              MyTransformer<String, Integer> transformProcessor = new MyTransformer<>(Integer::parseInt);
      
              TestSubscriber<Integer> subscriber = new TestSubscriber<>();
              List<String> items = List.of("1", "2", "3");
      
              List<Integer> expectedResult = List.of(1, 2, 3);
      
              publisher.subscribe(transformProcessor);
              transformProcessor.subscribe(subscriber);
              items.forEach(publisher::submit);
              publisher.close();
      
          }
      }