3.2、HTTP服务器Verticle
Verticle类的部分代码和启动方法如下所示:
public class HttpServerVerticle extends AbstractVerticle {
private static final Logger LOGGER = LoggerFactory.getLogger(HttpServerVerticle.class);
public static final String CONFIG_HTTP_SERVER_PORT = "http.server.port"; (1)
public static final String CONFIG_WIKIDB_QUEUE = "wikidb.queue";
private String wikiDbQueue = "wikidb.queue";
@Override
public void start(Future<Void> startFuture) throws Exception {
wikiDbQueue = config().getString(CONFIG_WIKIDB_QUEUE, "wikidb.queue"); (2)
HttpServer server = vertx.createHttpServer();
Router router = Router.router(vertx);
router.get("/").handler(this::indexHandler);
router.get("/wiki/:page").handler(this::pageRenderingHandler);
router.post().handler(BodyHandler.create());
router.post("/save").handler(this::pageUpdateHandler);
router.post("/create").handler(this::pageCreateHandler);
router.post("/delete").handler(this::pageDeletionHandler);
int portNumber = config().getInteger(CONFIG_HTTP_SERVER_PORT, 8080); (3)
server
.requestHandler(router::accept)
.listen(portNumber, ar -> {
if (ar.succeeded()) {
LOGGER.info("HTTP server running on port " + portNumber);
startFuture.complete();
} else {
LOGGER.error("Could not start a HTTP server", ar.cause());
startFuture.fail(ar.cause());
}
});
}
// (...)
- 我们公开Verticle配置参数中的公共常量:HTTP端口号 以及将消息发送到数据库Verticle的事件总线目的地的名称;
- AbstractVerticle#config()方法允许访问已经存在的由Verticle提供的配置。如果没有给出特定值,则第二个参数是默认值;
- 配置值不只可以是String对象,也可以是整数,布尔值,复杂的JSON数据等。
该类的其余部分主要是HTTP代码的摘录,以前的数据库代码使用事件总线消息替换。这是indexHandler方法代码:
private final FreeMarkerTemplateEngine templateEngine = FreeMarkerTemplateEngine.create();
private void indexHandler(RoutingContext context) {
DeliveryOptions options = new DeliveryOptions().addHeader("action", "all-pages"); (2)
vertx.eventBus().send(wikiDbQueue, new JsonObject(), options, reply -> { (1)
if (reply.succeeded()) {
JsonObject body = (JsonObject) reply.result().body(); (3)
context.put("title", "Wiki home");
context.put("pages", body.getJsonArray("pages").getList());
templateEngine.render(context, "templates", "/index.ftl", ar -> {
if (ar.succeeded()) {
context.response().putHeader("Content-Type", "text/html");
context.response().end(ar.result());
} else {
context.fail(ar.cause());
}
});
} else {
context.fail(reply.cause());
}
});
}
- vertx对象提供对事件总线的访问,我们发送消息到数据库队列 Verticle;
- 交付选项允许我们指定标题,有效载荷编解码器和超时时间
- 成功后,回复包含有效载荷。
我们可以看到,事件总线消息由一个主体,选项组成,它可以可选地期望一个回复。在没有响应的情况下,发送方法的变体没有处理程序。
我们将有效负载编码为JSON对象,我们通过称为"action"的消息头指定数据库verticle应该执行的操作。
此Verticle的其余代码在路由器处理程序中也使用事件总线来获取和存储数据: