Vert.x 示例
//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 示例的更多相关文章
- CSharpGL(39)GLSL光照示例:鼠标拖动太阳(光源)观察平行光的漫反射和镜面反射效果
CSharpGL(39)GLSL光照示例:鼠标拖动太阳(光源)观察平行光的漫反射和镜面反射效果 开始 一图抵千言.首先来看鼠标拖动太阳(光源)的情形. 然后是鼠标拖拽旋转模型的情形. 然后我们移动摄像 ...
- 编译opengl编程指南第八版示例代码通过
最近在编译opengl编程指南第八版的示例代码,如下 #include <iostream> #include "vgl.h" #include "LoadS ...
- Vert.x入门体验
Vert.x入门体验 一.概述 Vert.x(http://vertx.io)是一个基于JVM.轻量级.高性能的应用平台,非常适用于最新的移动端后台.互联网.企业应用架构. 二.安装配置 访问Vert ...
- 使用Vert.x构建Web服务器和消息系统
如果你对Node.js感兴趣,Vert.x可能是你的下一个大事件:一个建立在JVM上一个类似的架构企业制度. 这一部分介绍Vert.x是通过两个动手的例子(基于Vert.x 2.0). 当Node.j ...
- [转] VS2015中跑OpenGL红宝书第八版的第一章示例代码,运行
Ori Article Link OpenGL的东西快忘光了,把角落的第八版红宝书拿出来复习一下 从书中的地址下了个示例代码结果新系统(Win10+VS2015)各种跑不起来,懊恼之后在网上疯狂搜索资 ...
- VS2015中跑OpenGL红宝书第八版的示例代码
OpenGL的东西快忘光了,把角落的第八版红宝书拿出来复习一下 从书中的地址下了个示例代码结果新系统(Win10+VS2015)各种跑不起来,懊恼之后在网上疯狂搜索资料终于跑起来了,记录一下 一.环境 ...
- Vert.x Web之Router
Vert.x Web 是一系列用于基于 Vert.x 构建 Web 应用的构建模块. Vert.x Web 的大多数特性被实现为了处理器(Handler),因此您随时可以实现您自己的处理器.我们预计随 ...
- Vert.x学习之 Web Client
Vert.x Web Client 原文档 组件源码 组件示例 中英对照表 Pump:泵(平滑流式数据读入内存的机制,防止一次性将大量数据读入内存导致内存溢出) Response Codec:响应编解 ...
- Vert.x Web 文档手册
Vert.x Web 中英对照表 Container:容器 Micro-service:微服务 Bridge:桥接 Router:路由器 Route:路由 Sub-Route: 子路由 Handler ...
随机推荐
- 【noip模拟赛5】任务分配 降维dp
描述 现有n个任务,要交给A和B完成.每个任务给A或给B完成,所需的时间分别为ai和bi.问他们完成所有的任务至少要多少时间. 输入 第一行一个正整数n,表示有n个任务.接下来有n行,每行两个正整数a ...
- VsCode下代码导航
Visual Studio Code具有高效的代码编辑器,当与编程语言服务结合使用时,可以为您提供IDE的强大功能和文本编辑器的速度.在本主题中,我们将首先描述VS Code的语言智能功能(建议,参数 ...
- UVA 11624-Fire!【双BFS】
<题目链接> 题目大意: 你的任务是帮助J走出一个大火蔓延的迷宫.J每分钟可以超上下左右四个方向移动,而所有着火的格子每一分钟都会往四个方向蔓延一格.迷宫中有一些障碍,J和火都无法进入.当 ...
- ACM差分约束笔记
https://www.cnblogs.com/31415926535x/p/10463112.html 很早之前学最短路的时候就看了一眼差分约束,,当时以为这种问题不怎么会出现,,而且当时为了只为了 ...
- 我的Java自学之路
其实在转正之后我就想抽个时间好好的梳理一下我的 Java 上车之路 ,但是一直拖到现在 ,因为有学弟问到 ,所以也就给了我动力 .毕竟答应了人家的事要做到 . 首先要有相应的背景介绍 ,不然说个毛线啊 ...
- 潭州课堂25班:Ph201805201 爬虫基础 第四课 Requests (课堂笔记)
优雅到骨子里的Requests 1528811134432 简介 上一篇文章介绍了Python的网络请求库urllib和urllib3的使用方法,那么,作为同样是网络请求库的Request ...
- 公开课 之 tony 电子时钟 (课堂笔记)
# tony 之电子时钟from PyQt5.QtWidgets import QApplication, QWidget, QLCDNumber, QDesktopWidget, QVBoxLayo ...
- CAD画图技巧经验
1.CAD中如何输入特殊符号 %% d ——绘制“℃”符号.例如: 98.6 ℃—— 98.6 %% dC : %% c ——绘制圆直径“φ”符号.例如:φ 30 ——%% c30 : %% p —— ...
- C++学习笔记40:进程应用
进程创建 system()函数:用于在程序中执行一条命令 如果shell不能运行,返回127,如果发生其他错误返回-1: 例子:int ret_val = system(“ls -l /”); for ...
- vscode调试C/C++时支持查看定义查看引用
貌似老版支持现在不支持了,需要自己加第三方工具,方法如下: 确保你安装了c/c++,此文写作时版本为0.20.1 从GTAGS官网下载Win32程序,解压,将其放在合适的位置,并把其目录下/bin文件 ...