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 ...
随机推荐
- What Are You Talking About HDU1075
一开始我也想用map 但是处理不好其他字符.. 看了题解 多多学习! 很巧妙 就是粗暴的一个字符一个字符的来 分为小写字母和非小写字母两个部分 一但单词结束的时候就开始判断. #includ ...
- 【Java】 剑指offer(9) 斐波那契数列及青蛙跳台阶问题
本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集 题目 写一个函数,输入n,求斐波那契(Fibonacci)数列的第n项 ...
- c++中关于用stringstream进行的类型转化
1.将int转化成string类型 #include <iostream> #include <sstream> using namespace std; int main() ...
- jstl标签比较格式化后的时间
c:set 里面不支持任何标签,这样写不好讲格式化的值放到bdateVar里面 <c:set var="bdateVar" value="<fmt:forma ...
- 用VScode代码调试Python
Python扩展支持许多类型的Python应用程序的调试,包括以下一般功能: 观看窗口 评估表达式 当地人 参数 扩大孩子 断点 条件断点 暂停(进入)正在运行的程序 自定义启动目录 要熟悉这些常规功 ...
- [环境]vscode中python虚拟环境
在项目.vscode/settings.json下设置 { "python.pythonPath": "/path/to/python2.7"}
- PHP抓取网页内容经验总结
用php 抓取页面的内容在实际的开发当中是非常有用的,如作一个简单的内容采集器,提取网页中的部分内容等等,抓取到的内容在通过正则表达式做一下过滤就得到了你想要的内容,至于如何用正则表达式过滤,在这里就 ...
- yum 安装 jenkins
环境:已安装 tomcat 安装(如果yum下载速度比较忙可以下载下来再安装) yum -y install https://pkg.jenkins.io/redhat/jenkins-2.77-1. ...
- [Java web]Spring+Struts2+Hibernate整合过程
摘要 最近一直在折腾java web相关内容,这里就把最近学习的spring+struts2+hibernate进行一个整合,也就是大家经常说的ssh. 环境 工具IDE :Idea 2018 数据库 ...
- Delphi创建ActiveX控件,实现安全接口及无界面代码
Delphi创建OCX控件非常的方便,但IE调用时弹出的安全认证非常麻烦,有时OCX也不需要界面,IE调用时需要隐藏,非常不方便.在DELPHI中创建OCX实现安全接口和创建事件中修改部分代码 实现安 ...