问题
In terms of Reactive Streams, there is a Publisher and it could have as many Subscribers.
But suppose, a subscriber gets a message from Publisher. Now this Subscriber(say Subs1) changes/modifies the message and passes it to some other Subscriber(say Subs2), which consumes the modified message.
So can this Subs1 subscriber can act as a Publisher which can pass on message to new Subs2 subscriber?
I am not sure if it possible or not, but the scenario is possible i think.
If its possible, please suggest a possible way to do this.
回答1:
If we want to transform incoming message and pass it further to the next Subscriber, we need to implement the Processor interface. This acts both as a Subscriber because it receives messages, and as the Publisher because it processes those messages and sends them for further processing.
Here is the complete implementation to do this:
Create a MyTransformer class which implements Processor and extends SubmissionPublisher, as it will act both as Subscriber and Publisher:
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); } }
Create an TestSubscriber class which implements the Subscriber interface and implement the required methods:
The onSubscribe() method is called before processing starts. The instance of the Subscription is passed as the argument. It is a class that is used to control the flow of messages between Subscriber and the Publisher.
The main method here is onNext() – this is called whenever the Publisher publishes a new message.
We are using the SubmissionPublisher class which implements the Publisher interface.
We’re going to be submitting N elements to the Publisher – which our TestSubscriber will be receiving.
Note, that we’re calling the close() method on the instance of the TestSubscriber. It will invoke onComplete() callback underneath on every Subscriber of the given Publisher.
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);
}
}
- Here is processing flow in which the Publisher is publishing String elements.
MyTransformer is parsing the String as Integer – which means a conversion needs to happening here.
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();
}
}
来源:https://stackoverflow.com/questions/47936868/can-a-subscriber-act-as-a-publisher