R0001 - Rx模式的Vertx/Verticle实例
「平行章节」:1.3.Vertx实例、1.4.Verticle实例、1.5.Verticle生命周期
取名为“平行世界”,是希望读者在一边学习Vert.x正章的时候,使用Rxjava2的方式再熟悉一次Vert.x中的Rx的写法,我不太熟悉这种写法,因为直到今天zero中一直都没有使用它,但由于对Rxjava2的钟爱以及Rxjs写前端留下的沉淀,所以我也在尝试使用Rx的模式去写Vert.x的程序。平行世界的含义在于:
- Rx模式和通常开发模式的平行;
- 《逐陆记》中两种写法的教程进度的平行;
- 学习和分享的平行(我对Rxjava2的写法可以说是初学);
基础环境搭建,在Rx模式下,您可以选择两个不同的版本:Rxjava2和Rxjava,推荐使用Rxjava2,虽然Vert.x对Rxjava2的支持有可能没有Rxjava这么厚的底蕴,但毕竟是升级后的版本,思维上没有太大的变化,所以用Rxjava2更符合Reactive编程的进化,如果是Rxjava的版本,您可以直接参考:Vert.x - From zero to (micro) - hero这篇文章。如果要启用Rxjava2的编程,需要在您的pom.xml
文件中先引入下边的片段:
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-rx-java2</artifactId>
<version>3.7.0</version>
</dependency>
理论上来讲,所有在Vert.x中可以参考的教程,都可以在Rx模式找到对应的答案,也许Rx模式下的某些内容更加Reactive,这也是分享“平行世界”的初衷,就是将原封不动的教程案例转移到Rx模式,熟悉Rx模式的一些写法——很不幸的是zero框架本身不支持Rx模式,虽然开了个vertx-rx
的项目封装了相关的Container,但害怕自己没有办法驾驭,误人子弟,所以直到现在我都没有在vertx-rx
这个项目中花太多的功夫。《平行世界》一般是主要章节的间章,不会有太多相关的概念介绍,只是使用了rxjava2
的方式来书写同样的逻辑——注意rxjava
和rxjava2
的版本有一定的区别。
1. Rx模式中的Verticle实例
package io.vertx.rx._01.verticles;
import io.vertx.reactivex.core.AbstractVerticle;
public class RxLifeVerticle extends AbstractVerticle {
@Override
public void start() throws Exception {
System.out.println(Thread.currentThread().getName() +
": Start : " +
Thread.currentThread().getId()
+ ", Did: " + this.deploymentID());
}
@Override
public void stop() throws Exception {
System.out.println(Thread.currentThread().getName() +
": Start : " +
Thread.currentThread().getId()
+ ", Did: " + this.deploymentID());
}
}
在Verticle实例的编写上,除了基类为io.vertx.reactivex.core.AbstractVerticle
以外,就没有其他的差异了。
2. Rx模式中的Vertx实例
在主章节中,Vertx实例在启动时分了两种模式,并且最后统一调用,使用rxjava2
的方式时同样会这样做。
2.1. Launcher
package io.vertx.rx._01.launcher;
import io.vertx.reactivex.core.Vertx;
import java.util.function.Consumer;
public interface Launcher {
void start(Consumer<Vertx> startConsumer);
}
2.2. SingleLauncher
package io.vertx.rx._01.launcher;
import io.vertx.core.VertxOptions;
import io.vertx.reactivex.core.Vertx;
import java.util.function.Consumer;
public class SingleLauncher implements Launcher {
@Override
public void start(final Consumer<Vertx> consumer) {
final VertxOptions options = new VertxOptions();
final Vertx vertx = Vertx.vertx(options);
if (null != vertx) {
consumer.accept(vertx);
}
}
}
2.3. ClusterLauncher
package io.vertx.rx._01.launcher;
import io.vertx.core.VertxOptions;
import io.vertx.reactivex.core.Vertx;
import java.util.function.Consumer;
public class ClusterLauncher implements Launcher {
@Override
public void start(final Consumer<Vertx> consumer) {
final VertxOptions options = new VertxOptions();
Vertx.rxClusteredVertx(options)
.doOnSuccess(consumer::accept)
.doOnError(error -> {
if (null != error) {
error.printStackTrace();
}
}).subscribe();
}
}
2.4. MainLauncher
package io.vertx.rx._01.launcher;
import io.vertx.core.DeploymentOptions;
import io.vertx.rx._01.verticles.RxLifeVerticle;
public class MainLauncher {
public static void main(final String[] args) {
// 哪种模式?
final boolean isClustered = false;
final Launcher launcher = isClustered ? new ClusterLauncher() :
new SingleLauncher();
launcher.start(vertx -> {
// 发布模式
vertx.rxDeployVerticle(RxLifeVerticle.class.getName(),
new DeploymentOptions().setInstances(3))
.doOnSuccess(id -> {
System.out.println("Verticle: " + id + " has been deployed successfully!");
}).subscribe();
});
}
}
3. 总结
上边的程序最终输出如下:
vert.x-eventloop-thread-0: Start : 14, Did: aaac80e5-59ea-4d18-8a8c-c09d447c88a4
vert.x-eventloop-thread-1: Start : 15, Did: aaac80e5-59ea-4d18-8a8c-c09d447c88a4
vert.x-eventloop-thread-2: Start : 16, Did: aaac80e5-59ea-4d18-8a8c-c09d447c88a4
Verticle: aaac80e5-59ea-4d18-8a8c-c09d447c88a4 has been deployed successfully!
这里不需要过多的陈述,关于rxjava2
中的Single
的用法可参考《Rxjava2中的Single解析》。