//filename: MainVerticle.java

package io.vertx.guides.wiki;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.DeploymentOptions;
import io.vertx.core.Future; /**
* @author <a href="https://julien.ponge.org/">Julien Ponge</a>
*/
// tag::main[]
public class MainVerticle extends AbstractVerticle { @Override
public void start(Future<Void> startFuture) throws Exception { Future<String> dbVerticleDeployment = Future.future(); // <1>
vertx.deployVerticle(new WikiDatabaseVerticle(), dbVerticleDeployment.completer()); // <2> dbVerticleDeployment.compose(id -> { // <3> Future<String> httpVerticleDeployment = Future.future();
vertx.deployVerticle(
"io.vertx.guides.wiki.HttpServerVerticle", // <4>
new DeploymentOptions().setInstances(3), // <5>
httpVerticleDeployment.completer()); return httpVerticleDeployment; // <6> }).setHandler(ar -> { // <7>
if (ar.succeeded()) {
startFuture.complete();
} else {
startFuture.fail(ar.cause());
}
});
}
}
//filename: HttpServerVerticle.java

package io.vertx.guides.wiki;

import com.github.rjeschke.txtmark.Processor;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.Future;
import io.vertx.core.eventbus.DeliveryOptions;
import io.vertx.core.http.HttpServer;
import io.vertx.core.json.JsonObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.handler.BodyHandler;
import io.vertx.ext.web.templ.FreeMarkerTemplateEngine; import java.util.Date; /**
* @author <a href="https://julien.ponge.org/">Julien Ponge</a>
*/
// tag::start[]
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.get("/test/:msg").handler(this::pageTestHandler);
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());
}
});
} // (...)
// end::start[] // tag::indexHandler[]
private final FreeMarkerTemplateEngine templateEngine = FreeMarkerTemplateEngine.create(); private void indexHandler(RoutingContext context) {
LOGGER.info("首页"); 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());
}
});
}
// end::indexHandler[] // tag::rest[]
private static final String EMPTY_PAGE_MARKDOWN =
"# A new page\n" +
"\n" +
"Feel-free to write in Markdown!\n"; private void pageTestHandler(RoutingContext context) {
String msg = context.request().getParam("msg");
LOGGER.info(msg);
JsonObject message = new JsonObject().put("msg",msg); // message body
DeliveryOptions options = new DeliveryOptions().addHeader("action","test-msg");
vertx.eventBus().send("wikidb.queue",message,options, reply ->{
if(reply.succeeded()){
JsonObject body = (JsonObject) reply.result().body();
context.response().putHeader("Content-Type", "text/html;charset=utf-8");
context.response().end(body.getString("msg"));
}
else{
context.fail(reply.cause());
}
});
} private void pageRenderingHandler(RoutingContext context) { String requestedPage = context.request().getParam("page");
JsonObject request = new JsonObject().put("page", requestedPage); DeliveryOptions options = new DeliveryOptions().addHeader("action", "get-page");
vertx.eventBus().send(wikiDbQueue, request, options, reply -> { if (reply.succeeded()) {
JsonObject body = (JsonObject) reply.result().body(); boolean found = body.getBoolean("found");
String rawContent = body.getString("rawContent", EMPTY_PAGE_MARKDOWN);
context.put("title", requestedPage);
context.put("id", body.getInteger("id", -1));
context.put("newPage", found ? "no" : "yes");
context.put("rawContent", rawContent);
context.put("content", Processor.process(rawContent));
context.put("timestamp", new Date().toString()); templateEngine.render(context, "templates","/page.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());
}
});
} private void pageUpdateHandler(RoutingContext context) { String title = context.request().getParam("title");
JsonObject request = new JsonObject()
.put("id", context.request().getParam("id"))
.put("title", title)
.put("markdown", context.request().getParam("markdown")); DeliveryOptions options = new DeliveryOptions();
if ("yes".equals(context.request().getParam("newPage"))) {
options.addHeader("action", "create-page");
} else {
options.addHeader("action", "save-page");
} vertx.eventBus().send(wikiDbQueue, request, options, reply -> {
if (reply.succeeded()) {
context.response().setStatusCode(303);
context.response().putHeader("Location", "/wiki/" + title);
context.response().end();
} else {
context.fail(reply.cause());
}
});
} private void pageCreateHandler(RoutingContext context) {
String pageName = context.request().getParam("name");
String location = "/wiki/" + pageName;
if (pageName == null || pageName.isEmpty()) {
location = "/";
}
context.response().setStatusCode(303);
context.response().putHeader("Location", location);
context.response().end();
} private void pageDeletionHandler(RoutingContext context) {
String id = context.request().getParam("id");
JsonObject request = new JsonObject().put("id", id);
DeliveryOptions options = new DeliveryOptions().addHeader("action", "delete-page");
vertx.eventBus().send(wikiDbQueue, request, options, reply -> {
if (reply.succeeded()) {
context.response().setStatusCode(303);
context.response().putHeader("Location", "/");
context.response().end();
} else {
context.fail(reply.cause());
}
});
}
// end::rest[]
}

  

//filename: WikiDatabaseVerticle.java

package io.vertx.guides.wiki;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.Future;
import io.vertx.core.eventbus.Message;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.jdbc.JDBCClient;
import io.vertx.ext.sql.ResultSet;
import io.vertx.ext.sql.SQLConnection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;
import java.util.stream.Collectors; /**
* @author <a href="https://julien.ponge.org/">Julien Ponge</a>
*/
// tag::preamble[]
public class WikiDatabaseVerticle extends AbstractVerticle { public static final String CONFIG_WIKIDB_JDBC_URL = "wikidb.jdbc.url";
public static final String CONFIG_WIKIDB_JDBC_DRIVER_CLASS = "wikidb.jdbc.driver_class";
public static final String CONFIG_WIKIDB_JDBC_MAX_POOL_SIZE = "wikidb.jdbc.max_pool_size";
public static final String CONFIG_WIKIDB_SQL_QUERIES_RESOURCE_FILE = "wikidb.sqlqueries.resource.file"; public static final String CONFIG_WIKIDB_QUEUE = "wikidb.queue"; private static final Logger LOGGER = LoggerFactory.getLogger(WikiDatabaseVerticle.class); // (...)
// end::preamble[] // tag::loadSqlQueries[]
private enum SqlQuery {
CREATE_PAGES_TABLE,
ALL_PAGES,
GET_PAGE,
CREATE_PAGE,
SAVE_PAGE,
DELETE_PAGE
} private final HashMap<SqlQuery, String> sqlQueries = new HashMap<>(); private void loadSqlQueries() throws IOException { String queriesFile = config().getString(CONFIG_WIKIDB_SQL_QUERIES_RESOURCE_FILE);
InputStream queriesInputStream;
if (queriesFile != null) {
queriesInputStream = new FileInputStream(queriesFile);
} else {
queriesInputStream = getClass().getResourceAsStream("/db-queries.properties");
} Properties queriesProps = new Properties();
queriesProps.load(queriesInputStream);
queriesInputStream.close(); sqlQueries.put(SqlQuery.CREATE_PAGES_TABLE, queriesProps.getProperty("create-pages-table"));
sqlQueries.put(SqlQuery.ALL_PAGES, queriesProps.getProperty("all-pages"));
sqlQueries.put(SqlQuery.GET_PAGE, queriesProps.getProperty("get-page"));
sqlQueries.put(SqlQuery.CREATE_PAGE, queriesProps.getProperty("create-page"));
sqlQueries.put(SqlQuery.SAVE_PAGE, queriesProps.getProperty("save-page"));
sqlQueries.put(SqlQuery.DELETE_PAGE, queriesProps.getProperty("delete-page"));
}
// end::loadSqlQueries[] // tag::start[]
private JDBCClient dbClient; @Override
public void start(Future<Void> startFuture) throws Exception { /*
* Note: this uses blocking APIs, but data is small...
*/
loadSqlQueries(); // <1> dbClient = JDBCClient.createShared(vertx, new JsonObject()
.put("url", config().getString(CONFIG_WIKIDB_JDBC_URL, "jdbc:hsqldb:file:db/wiki"))
.put("driver_class", config().getString(CONFIG_WIKIDB_JDBC_DRIVER_CLASS, "org.hsqldb.jdbcDriver"))
.put("max_pool_size", config().getInteger(CONFIG_WIKIDB_JDBC_MAX_POOL_SIZE, 30))); dbClient.getConnection(ar -> {
if (ar.failed()) {
LOGGER.error("Could not open a database connection", ar.cause());
startFuture.fail(ar.cause());
} else {
SQLConnection connection = ar.result();
connection.execute(sqlQueries.get(SqlQuery.CREATE_PAGES_TABLE), create -> { // <2>
connection.close();
if (create.failed()) {
LOGGER.error("Database preparation error", create.cause());
startFuture.fail(create.cause());
} else {
vertx.eventBus().consumer(config().getString(CONFIG_WIKIDB_QUEUE, "wikidb.queue"), this::onMessage); // <3>
startFuture.complete();
}
});
}
});
}
// end::start[] // tag::onMessage[]
public enum ErrorCodes {
NO_ACTION_SPECIFIED,
BAD_ACTION,
DB_ERROR
} public void onMessage(Message<JsonObject> message) { if (!message.headers().contains("action")) {
LOGGER.error("No action header specified for message with headers {} and body {}",
message.headers(), message.body().encodePrettily());
message.fail(ErrorCodes.NO_ACTION_SPECIFIED.ordinal(), "No action header specified");
return;
}
String action = message.headers().get("action"); switch (action) {
case "all-pages":
fetchAllPages(message);
break;
case "get-page":
fetchPage(message);
break;
case "test-msg":
testMsg(message);
break;
case "create-page":
createPage(message);
break;
case "save-page":
savePage(message);
break;
case "delete-page":
deletePage(message);
break;
default:
message.fail(ErrorCodes.BAD_ACTION.ordinal(), "Bad action: " + action);
}
}
// end::onMessage[] // tag::rest[]
private void fetchAllPages(Message<JsonObject> message) { dbClient.getConnection(car -> {
if (car.succeeded()) {
SQLConnection connection = car.result();
connection.query(sqlQueries.get(SqlQuery.ALL_PAGES), res -> {
connection.close();
if (res.succeeded()) {
List<String> pages = res.result()
.getResults()
.stream()
.map(json -> json.getString(0))
.sorted()
.collect(Collectors.toList());
message.reply(new JsonObject().put("pages", new JsonArray(pages)));
} else {
reportQueryError(message, res.cause());
}
});
} else {
reportQueryError(message, car.cause());
}
});
} private void testMsg(Message<JsonObject> message) {
String msg = message.body().getString("msg");
LOGGER.info(msg);
if (!"error".equals(msg)) {
JsonObject response = new JsonObject();
response.put("msg", "您好,我是WikiDatabaseVerticle: " + msg);
message.reply(response);
} else {
message.fail(-1, "你的输入有误!");
}
} private void fetchPage(Message<JsonObject> message) { String requestedPage = message.body().getString("page"); dbClient.getConnection(car -> {
if (car.succeeded()) {
SQLConnection connection = car.result();
connection.queryWithParams(sqlQueries.get(SqlQuery.GET_PAGE), new JsonArray().add(requestedPage), fetch -> {
connection.close();
if (fetch.succeeded()) {
JsonObject response = new JsonObject();
ResultSet resultSet = fetch.result();
if (resultSet.getNumRows() == 0) {
response.put("found", false);
} else {
response.put("found", true);
JsonArray row = resultSet.getResults().get(0);
response.put("id", row.getInteger(0));
response.put("rawContent", row.getString(1));
}
message.reply(response);
} else {
reportQueryError(message, fetch.cause());
}
});
} else {
reportQueryError(message, car.cause());
}
}); } private void createPage(Message<JsonObject> message) {
JsonObject request = message.body(); dbClient.getConnection(car -> { if (car.succeeded()) {
SQLConnection connection = car.result();
JsonArray data = new JsonArray()
.add(request.getString("title"))
.add(request.getString("markdown")); connection.updateWithParams(sqlQueries.get(SqlQuery.CREATE_PAGE), data, res -> {
connection.close();
if (res.succeeded()) {
message.reply("ok");
} else {
reportQueryError(message, res.cause());
}
});
} else {
reportQueryError(message, car.cause());
}
});
} private void savePage(Message<JsonObject> message) {
JsonObject request = message.body(); dbClient.getConnection(car -> { if (car.succeeded()) {
SQLConnection connection = car.result();
JsonArray data = new JsonArray()
.add(request.getString("markdown"))
.add(request.getString("id")); connection.updateWithParams(sqlQueries.get(SqlQuery.SAVE_PAGE), data, res -> {
connection.close();
if (res.succeeded()) {
message.reply("ok");
} else {
reportQueryError(message, res.cause());
}
});
} else {
reportQueryError(message, car.cause());
}
});
} private void deletePage(Message<JsonObject> message) {
dbClient.getConnection(car -> {
if (car.succeeded()) {
SQLConnection connection = car.result();
JsonArray data = new JsonArray().add(message.body().getString("id"));
connection.updateWithParams(sqlQueries.get(SqlQuery.DELETE_PAGE), data, res -> {
connection.close();
if (res.succeeded()) {
message.reply("ok");
} else {
reportQueryError(message, res.cause());
}
});
} else {
reportQueryError(message, car.cause());
}
});
} private void reportQueryError(Message<JsonObject> message, Throwable cause) {
LOGGER.error("Database query error", cause);
message.fail(ErrorCodes.DB_ERROR.ordinal(), cause.getMessage());
}
// end::rest[]
}

  

  

Vert.x 示例的更多相关文章

  1. CSharpGL(39)GLSL光照示例:鼠标拖动太阳(光源)观察平行光的漫反射和镜面反射效果

    CSharpGL(39)GLSL光照示例:鼠标拖动太阳(光源)观察平行光的漫反射和镜面反射效果 开始 一图抵千言.首先来看鼠标拖动太阳(光源)的情形. 然后是鼠标拖拽旋转模型的情形. 然后我们移动摄像 ...

  2. 编译opengl编程指南第八版示例代码通过

    最近在编译opengl编程指南第八版的示例代码,如下 #include <iostream> #include "vgl.h" #include "LoadS ...

  3. Vert.x入门体验

    Vert.x入门体验 一.概述 Vert.x(http://vertx.io)是一个基于JVM.轻量级.高性能的应用平台,非常适用于最新的移动端后台.互联网.企业应用架构. 二.安装配置 访问Vert ...

  4. 使用Vert.x构建Web服务器和消息系统

    如果你对Node.js感兴趣,Vert.x可能是你的下一个大事件:一个建立在JVM上一个类似的架构企业制度. 这一部分介绍Vert.x是通过两个动手的例子(基于Vert.x 2.0). 当Node.j ...

  5. [转] VS2015中跑OpenGL红宝书第八版的第一章示例代码,运行

    Ori Article Link OpenGL的东西快忘光了,把角落的第八版红宝书拿出来复习一下 从书中的地址下了个示例代码结果新系统(Win10+VS2015)各种跑不起来,懊恼之后在网上疯狂搜索资 ...

  6. VS2015中跑OpenGL红宝书第八版的示例代码

    OpenGL的东西快忘光了,把角落的第八版红宝书拿出来复习一下 从书中的地址下了个示例代码结果新系统(Win10+VS2015)各种跑不起来,懊恼之后在网上疯狂搜索资料终于跑起来了,记录一下 一.环境 ...

  7. Vert.x Web之Router

    Vert.x Web 是一系列用于基于 Vert.x 构建 Web 应用的构建模块. Vert.x Web 的大多数特性被实现为了处理器(Handler),因此您随时可以实现您自己的处理器.我们预计随 ...

  8. Vert.x学习之 Web Client

    Vert.x Web Client 原文档 组件源码 组件示例 中英对照表 Pump:泵(平滑流式数据读入内存的机制,防止一次性将大量数据读入内存导致内存溢出) Response Codec:响应编解 ...

  9. Vert.x Web 文档手册

    Vert.x Web 中英对照表 Container:容器 Micro-service:微服务 Bridge:桥接 Router:路由器 Route:路由 Sub-Route: 子路由 Handler ...

随机推荐

  1. with 重写enter exit 方法

  2. Reinforcement Learning 的那点事——强化学习(一)

    引言 最近实验室的项目需要用到强化学习的有关内容,就开始学习起强化学习了,这里准备将学习的一些内容记录下来,作为笔记,方便日后忘记了好再方便熟悉,也可供大家参考.该篇为强化学习开篇文章,主要概括一些有 ...

  3. IdentityServer4-用EF配置Client(一)

    一.背景 IdentityServer4的介绍将不再叙述,百度下可以找到,且官网的快速入门例子也有翻译的版本.这里主要从Client应用场景方面介绍对IdentityServer4的应用. 首先简要介 ...

  4. hystrix dashboard Unable to connect to Command Metric Stream解决办法

    spring cloud 在初次使用 hystrix dashboard仪表盘的时候很容易出现hystrix dashboard Unable to connect to Command Metric ...

  5. Nuxt.js 如何在 asyncData中 请求数据 ,并将拿到的数据传给子组件

    说明:同接口请求一样,也可以进行数据的处理:return  中 左侧的变量  可以直接拿到在页面上使用,也可以传递给子组件 下面再给出一段代码,方便觉得有用的.却又不想手敲的朋友们: async as ...

  6. L1 与 L2 正则化

    参考这篇文章: https://baijiahao.baidu.com/s?id=1621054167310242353&wfr=spider&for=pc https://blog. ...

  7. 虚拟机Ping不通主机解决

    最近,装了一个虚拟机(Ubuntu-server-12.04),使用的桥接的方式.装完之后发现,主机可以ping通虚拟机,但是虚拟机可以ping通除主机之外的所有的IP(包括网关,DNS,还有其他的i ...

  8. python魔法方法-比较相关

    在python2.x的版本中,支持不同类型的比较,其比较原则如下: 内置类型: 1.同一类型:   1.1)数字类型:包含int.float.long.complex.bool(bool类型是int的 ...

  9. 发布Docker 镜像到dockerhub

    公有仓库 docker提供了一个类似于github的仓库dockerhub, 网址 https://hub.docker.com/ 需要注册使用 注意要保证image的tag是账户名,如果镜像名字不对 ...

  10. PHPMailer 使用方法(支持群发):

    一.下载函数包 地址:https://github.com/PHPMailer/PHPMailer 二.测试服务器环境 通过phpinfo()函数打印出是否支持Sockets(Socket属于php的 ...