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 ...
随机推荐
- 003 将spark源码导入到IDEA中
1.解压源代码 2.进入IDEA的首界面 3.使用open将解压的工程加载 4.将文件的形式改成maven项目 5.使用
- 安装及配置sublime
纯个人笔记,粗略编写,有时间再修改 参考:关于Sublime text3 配置及插件整理 参考:https://github.com/boontime/sublime-text3-config 参考: ...
- 【Ray Tracing The Next Week 超详解】 光线追踪2-5
Chapter 5:Image Texture Mapping 先看效果: 我们之前的纹理是利用的是撞击点p处的位置信息,比如大理石纹理 而我们今天的图片映射纹理采用2D(u,v)纹理坐标来进行. 在 ...
- 洛谷.1110.[ZJOI2007]报表统计(Multiset Heap)
题目链接 主要思路 /* 对于询问1,用堆代替multiset/Splay 对于询问2,multiset 1.注意哨兵元素 2.注意multiset中删除时是删除某元素的一个位置,而不是这个元素!这个 ...
- Ajax csrf跨站请求伪造
方式一: ///仅限js代码在HTML内//// $.ajaxSetup({ data: {csrfmiddlewaretoken: '{{ csrf_token }}' }, }); 方式二: // ...
- [HNOI2011]Problem B
Description: 给定\(a\),\(b\),\(c\),\(d\),\(k\) 求: \(\sum_{i=a}^{b} \sum_{j=c}^{d} gcd(i,j)==k\) \(T\)组 ...
- BZOJ1166 : [Baltic2008]Magical Stones
考虑二分答案,转化为求有多少$\leq lim$的数满足条件. 从两侧往中间进行数位DP,设$f[l][r][j][x][y][z][pre][suf]$表示当前准备填的两个位置是$l$和$r$,已经 ...
- Saltstack 分发
把master上的hosts文件分发到所有主机 [root@node1 ~]# salt-cp '*' /etc/hosts /etc
- linux系统下shell命令中的sleep
在有的shell(比如linux中的bash)中sleep还支持睡眠(分,小时)sleep 1 睡眠1秒sleep 1s 睡眠1秒sleep 1m 睡眠1分sleep 1h 睡眠1 ...
- Object类--toString方法
toString()方法 1.在Object类中定义toString()方法的时候返回对象的哈希code码(对象地址字符串) 直接输出对象: 2.可以通过重写toString()方法表示出对象的属性之 ...