Reactor 3 响应式编程设计与实现概述
一、响应式规范中定义了四个接口:
1、Publisher
Publisher是能够发布元素的发布者
2、Subscriber
Subscriber是订阅者,能够订阅发布者发布的元素及事件
3、Subscription
Subscription是表示一次订阅关系的声明周期
4、Processor
Processor是一个处理过程,它既能够订阅发布者发布的元素及事件, 又能对外提供元素及事件的发布,非常适合用来做对元素中间过程的处理
四个接口之间的关系如下图:
public interface Publisher<T> {
void subscribe(Subscriber<? super <T>subscriber);
}
public interface Subscriber<T> {
void onSubscribe(Subscription subscription);
void onNext(T item);
void onError(Throwable throwable);
void onComplete();
}
public interface Subscription {
void request(long n);
void cancel();
}
public interface Processor<T, R> extends Subscriber<T>, Publisher<R> {
}
二、根据关系图,我们尝试依据接口规范,来实现一下
1、实现Publisher
public class PublisherImpl<T> implements Publisher<T> {
private final T[] array;
public PublisherImpl(T[] array) {
this.array = array;
}
@Override
public void subscribe(Subscriber<? super T> s) {
s.onSubscribe(new SubscriptionImpl<>(s, array));
}
}
2、实现Subscription
public class SubscriptionImpl<T> implements Subscription {
private final Subscriber<T> subscriber;
private final T[] array;
private boolean cancel;
public SubscriptionImpl(Subscriber<T> s, T[] array) {
this.subscriber = s;
this.array = array;
}
@Override
public void request(long n) {
if (cancel) {
return;
}
try {
for (int i = 0; i < n && i < array.length; i++) {
subscriber.onNext(array[i]);
}
subscriber.onComplete();
} catch (Exception e) {
subscriber.onError(e);
}
}
@Override
public void cancel() {
this.cancel = true;
}
}
3、实现Subscriber
public class SubscriberImpl<T> implements Subscriber<T> {
private Subscription s;
@Override
public void onSubscribe(Subscription s) {
this.s = s;
s.request(Long.MAX_VALUE);
}
@Override
public void onNext(T s) {
System.out.println("接收到了元素:" + s);
if (s.equals("error")) {
throw new RuntimeException("消费到异常数据");
}
}
@Override
public void onError(Throwable t) {
System.out.println("接收到了异常信号:" + t.getMessage());
}
@Override
public void onComplete() {
System.out.println("接收到了完成信号");
}
}
4、接下来编写测试来,来测试下元素的发布及订阅是否正常:
public class Test {
@Test
public void test() {
Publisher<String> publisher = new PublisherImpl<>(new String[]{"a", "b", "c", "d"});
publisher.subscribe(new SubscriberImpl<>());
}
}
可以看到能够正常发布并且被消费者正确消费到。
如果在发布或消费的过程中产生了异常,订阅者应该也能接收到异常信号,并且不会接受到完成信号。
5、修改单测,测试消费到指定元素时抛出异常
public class Test {
@Test
public void test2() {
Publisher<String> publisher = new PublisherImpl<>(new String[]{"a", "b", "error", "c", "d"});
publisher.subscribe(new SubscriberImpl<>());
}
}
单测中发布了5个元素:“a”, “b”, “error”, “c”, “d”, 其中第三个元素表示是异常元素,消费到该元素后,发布者将发布异常信号,该信号将被订阅者感知到。