上节讲了,Verticle实例有start()和stop()方法,你可以在这两个方法中实现具体工作然后将实例注册到Vertx实例中将自动调用这两个方法。verticle有些类似Servlet或者JavaEE中事件驱动的EJB,但是要实现并发处理,verticle的工作模式与前两者并不同。本节将介绍如何注册verticle到vertx以及verticle内部之间如何通过eventbus互相通信。
首先创建一个继承自io.vertx.core.AbstractVerticle的类:
import io.vertx.core.AbstractVerticle;
public class BasicVerticle extends AbstractVerticle {
}
你已经创建了一个BasicVerticle类,但是它还不包含任何方法,下面添加start()和stop()方法。
AbstractVerticle类包含了start()方法,你可以override它并在里面添加你想让它去做的工作,如:
public class BasicVerticle extends AbstractVerticle {
@Override
public void start() throws Exception {
System.out.println("BasicVerticle started");
}
}
这里只是打印了一串字符。原则上start()里面可以做任何它应当做的事情,比如initialize当前verticle、创建一个HTTP或TCP Server、给EventBus注册Event Handlers、或者注册其它Verticle实例到Vertx实例等。
start()方法还有另外一个用法,那就是传递一个Future对象的参数,如:
public class BasicVerticle extends AbstractVerticle {
@Override
public void start(Future future) throws Exception {
System.out.println("BasicVerticle started");
}
}
Future对象参数可以用来异步的告诉Vertx实例是否此次注册verticle成功了。
stop()方法在vertx实例停止的时候或者当verticle被从vertx实例卸载的时候。下面是在自己类中对它的覆盖:
public class BasicVerticle extends AbstractVerticle {
@Override
public void start() throws Exception {
System.out.println("BasicVerticle started");
}
@Override
public void stop() throws Exception {
System.out.println("BasicVerticle stopped");
}
}
创建完成自己的Verticle类BasicVerticle之后,就可以注册它到Vert.x实例中了:
public class VertxVerticleMain {
public static void main(String[] args) throws InterruptedException {
Vertx vertx = Vertx.vertx();
vertx.deployVerticle(new BasicVerticle());
}
}
需要注意两点:第一,当vertx.deployVerticle(new BasicVerticle());执行时,Verticle的start()方法将会被调用;第二,vertx.deployVerticle()方法是异步将Verticle实例配置(注册),所以当该方法返回时,可能并没有注册完成,要想确切的知道何时被成功注册了,你可以通过提供一个Handler完成,如:
vertx.deployVerticle(new BasicVerticle(), new Handler>() {
@Override
public void handle(AsyncResult stringAsyncResult) {
System.out.println("BasicVerticle deployment complete");
}
});
或者使用Java中的lambda表达式:
vertx.deployVerticle(new BasicVerticle(), stringAsyncResult -> {
System.out.println("BasicVerticle deployment complete");
});
可以在一个verticle内部注册其它的verticle,比如:
public class BasicVerticle extends AbstractVerticle {
@Override
public void start() throws Exception {
System.out.println("BasicVerticle started");
vertx.deployVerticle(new SecondVerticle());
}
@Override
public void stop() throws Exception {
System.out.println("BasicVerticle stopped");
}
}
请读者自行体会这样做会带来程序业务逻辑上的层次流程关系。
verticle可以监听到来自Event bus的消息,也可以给Event bus写消息。
verticle监听来自Event bus的消息,是通过一个自定义的“Address”实现的,该“Address”是可以随意定义的一个字符串名称。
多个verticles可以监听同一个“Address”的消息,也可以给同一个“Address”发送消息。
public class MyVerticle extends AbstractVerticle {
public void start(Future startFuture) {
vertx.eventBus().consumer("anAddress", message -> {
System.out.println("1 received message.body() = "
+ message.body());
});
}
}
我们在start()中让MyVerticle监听来自Event Bus的anAddress地址的消息。
给Event bus发送消息可以通过send()或publish()完成。
publish()方法发送的消息会被监听在该地址的所有verticle接收,注意是所有。
send()方法发送的消息只会被监听在该地址的其中一个verticle接收,到底哪个接收由vertx决定,vertx怎么决定的呢?官方解释是通过“non-strict round robin”原则,简单理解就是按照不严格的规则随机的选择一个verticle收到该消息。请读者自己琢磨send()这种方式的好处。
Vertx vertx = Vertx.vertx();
vertx.deployVerticle(new EventBusReceiverVerticle("R1"));
vertx.deployVerticle(new EventBusReceiverVerticle("R2"));
Thread.sleep(3000);
vertx.deployVerticle(new EventBusSenderVerticle());
public class EventBusSenderVerticle extends AbstractVerticle {
public void start(Future startFuture) {
vertx.eventBus().publish("anAddress", "message 2");
vertx.eventBus().send ("anAddress", "message 1");
}
}
public class EventBusReceiverVerticle extends AbstractVerticle {
private String name = null;
public EventBusReceiverVerticle(String name) {
this.name = name;
}
public void start(Future startFuture) {
vertx.eventBus().consumer("anAddress", message -> {
System.out.println(this.name +
" received message: " +
message.body());
});
}
}
运行以上代码,你将会看到message 2会被两个verticle接收到,而message 1只会被其中一个接收。