Vert.x Web之Router
Vert.x Web 是一系列用于基于 Vert.x 构建 Web 应用的构建模块。
Vert.x Web 的大多数特性被实现为了处理器(Handler),因此您随时可以实现您自己的处理器。我们预计随着时间的推移会有更多的处理器被实现。
使用 Vert.x Web
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web</artifactId>
<version>3.4.2</version>
</dependency>
回顾 Vert.x Core 的 HTTP 服务端
HttpServer server = vertx.createHttpServer();
server.requestHandler(request -> {
// 所有的请求都会调用这个处理器处理
HttpServerResponse response = request.response();
response.putHeader("content-type", "text/plain");
// 写入响应并结束处理
response.end("Hello World!");
});
server.listen(8080);
Vert.x Web 的基本概念
Router 是 Vert.x Web 的核心概念之一。它是一个维护了零或多个 Route 的对象。
Router 接收 HTTP 请求,并查找首个匹配该请求的 Route,然后将请求传递给这个 Route。
Route 可以持有一个与之关联的处理器用于接收请求。您可以通过这个处理器对请求做一些事情,然后结束响应或者把请求传递给下一个匹配的处理器。
以下是一个简单的路由示例:
HttpServer server = vertx.createHttpServer();
Router router = Router.router(vertx);
router.route().handler(routingContext -> {
// 所有的请求都会调用这个处理器处理
HttpServerResponse response = routingContext.response();
response.putHeader("content-type", "text/plain");
// 写入响应并结束处理
response.end("Hello World from Vert.x-Web!");
});
server.requestHandler(router::accept).listen(8080);
做了和上文使用 Vert.x Core 实现的 HTTP 服务器基本相同的事情,只是这一次换成了 Vert.x Web。
和上文一样,我们创建了一个 HTTP 服务器,然后创建了一个 Router。在这之后,我们创建了一个没有匹配条件的 Route,这个 route 会匹配所有到达这个服务器的请求。
之后,我们为这个 route 指定了一个处理器,所有的请求都会调用这个处理器处理。
调用处理器的参数是一个 RoutingContext 对象。它不仅包含了 Vert.x 中标准的 HttpServerRequest 和HttpServerResponse,还包含了各种用于简化 Vert.x Web 使用的东西。
每一个被路由的请求对应一个唯一的 RoutingContext,这个实例会被传递到所有处理这个请求的处理器上。
处理请求并调用下一个处理器
当 Vert.x Web 决定路由一个请求到匹配的 route 上,它会使用一个 RoutingContext 调用对应处理器。
如果您不在处理器里结束这个响应,您需要调用 next 方法让其他匹配的 Route 来处理请求(如果有)。
您不需要在处理器执行完毕时调用 next 方法。您可以在之后您需要的时间点调用它:
Route route1 = router.route("/some/path/").handler(routingContext -> {
HttpServerResponse response = routingContext.response();
// 由于我们会在不同的处理器里写入响应,因此需要启用分块传输
// 仅当需要通过多个处理器输出响应时才需要
response.setChunked(true);
response.write("route1\n");
// 5 秒后调用下一个处理器
routingContext.vertx().setTimer(5000, tid -> routingContext.next());
});
Route route2 = router.route("/some/path/").handler(routingContext -> {
HttpServerResponse response = routingContext.response();
response.write("route2\n");
// 5 秒后调用下一个处理器
routingContext.vertx().setTimer(5000, tid -> routingContext.next());
});
Route route3 = router.route("/some/path/").handler(routingContext -> {
HttpServerResponse response = routingContext.response();
response.write("route3");
// 结束响应
routingContext.response().end();
});
在上述的例子中,route1 向响应里写入了数据,5秒之后 route2 向响应里写入了数据,再5秒之后 route3 向响应里写入了数据并结束了响应。
注意,所有发生的这些没有线程阻塞。
下面看一个route自写的例子
public class FirstMain extends AbstractVerticle {
private static Logger logger = LoggerFactory.getLogger(FirstMain.class);
public void start() {
HttpServer server = vertx.createHttpServer();
Router router = Router.router(vertx);
router.get("/hang/some").handler(routingContext -> { //指定get方法
// 所有的请求都会调用这个处理器处理
HttpServerResponse response = routingContext.response();
response.putHeader("content-type", "text/plain");
// 写入响应并结束处理
response.end("Hello World from Vert.x-Web!");
});
router.route("/hang/all").handler(routingContext -> {
// 所有的请求都会调用这个处理器处理
HttpServerResponse response = routingContext.response();
response.putHeader("content-type", "text/plain");
// 写入响应并结束处理
response.end("Hello World !");
});
router.route("/hang/put").handler(BodyHandler::getStr);
// router.route("/static/*").handler(StaticHandler.create());
//处理请求并调用下一个处理器
router.route(HttpMethod.POST,"/hang/add").handler(BodyHandler::getStr_1);//OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT, PATCH, OTHER
router.route("/hang/add").handler(BodyHandler::getStr_2);
router.route("/hang/add").handler(BodyHandler::getStr_3);
router.route("/hello").blockingHandler(BodyHandler.bodyHandler()::getStr_4, false);
server.requestHandler(router::accept).listen(8080);
}
public static void main(String[] args) {
// Vertx vertx = Vertx.vertx(new VertxOptions().setWorkerPoolSize(40));
// vertx.deployVerticle(FirstMain.class.getName());
// System.out.println("vertx......启动");
Vertx.clusteredVertx(new VertxOptions(), res->{
if (res.succeeded()) {
res.result().deployVerticle(FirstMain.class.getName());
logger.info("success start!" );
System.out.println("success start!" );
} else {
logger.info("Failed: " + res.cause());
}
});
}
}
BodyHandler类:
public class BodyHandler {
// private Vertx vertx;
private static BodyHandler bodyHandler = new BodyHandler();
public Logger logger = LoggerFactory.getLogger(BodyHandler.class);
public static BodyHandler bodyHandler() {
return bodyHandler;
}
public static void getStr(RoutingContext rc){
rc.response().end("Hello world! 我!");
}
public static void getStr_1(RoutingContext rc){
HttpServerResponse response = rc.response();
// 由于我们会在不同的处理器里写入响应,因此需要启用分块传输,仅当需要通过多个处理器输出响应时才需要
response.setChunked(true);
response.write("我");
rc.next();
// 5 秒后调用下一个处理器
// rc.vertx().setTimer(5000, tid -> rc.next());
}
public static void getStr_2(RoutingContext rc){
HttpServerResponse response = rc.response();
response.write("和");
rc.next();
}
public static void getStr_3(RoutingContext rc){
HttpServerResponse response = rc.response();
response.write("你");
rc.response().end();
}
public void getStr_4(RoutingContext rc){
ObjectMapper om = new ObjectMapper();
if ("1".equals("1")) {
getOrder("1", res -> {
if (res.succeeded()) {
try {
rc.response().putHeader("Content-type", "application/json; charset=UTF-8");
rc.response().end(om.writeValueAsString(res.result()));
System.out.println("我是第四个打印!");
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}else{
rc.response().setStatusCode(500)
.putHeader("Content-type", "application/json; charset=UTF-8")
.end((Buffer) new JsonObject().put("status", 0).put("des", "fali"));
}
});
System.out.println("我是第一个打印!");
}
}
private void getOrder(String orderId, Handler<AsyncResult<String>> handler){
Vertx vertx = Vertx.vertx(new VertxOptions().setWorkerPoolSize(40));
vertx.<String>executeBlocking(future -> {
try {
Thread.sleep(1);
System.out.println("我是第二个打印!");
future.complete("成功!");
} catch (InterruptedException e) {
e.printStackTrace();
}
},false, res->{
if (res.succeeded()) {
System.out.println("我是第三个打印!");
handler.handle(Future.succeededFuture(res.result()));
} else {
handler.handle(Future.failedFuture(res.cause()));
}
});
}
}
访问 http://localhost:8080//hang/some 得到:Hello World from Vert.x-Web!
访问 http://localhost:8080//hang/all 得到:Hello World !
访问 http://localhost:8080//hang/put 得到:Hello world! 我!
访问 http://localhost:8080/hang/add 得到:我和你 (post方式)
访问 http://localhost:8080/helo 得到:"成功!"
并输出如下:
我是第一个打印!
我是第二个打印!
我是第三个打印!
我是第四个打印!
Vert.x Web之Router的更多相关文章
- Vert.x Web 文档手册
Vert.x Web 中英对照表 Container:容器 Micro-service:微服务 Bridge:桥接 Router:路由器 Route:路由 Sub-Route: 子路由 Handler ...
- Vert.x Web
https://vertx.io/docs/vertx-web/java/ Vert.x-Web是一组用于使用Vert.x构建Web应用程序的构建块.将其视为瑞士军刀,用于构建现代,可扩展的网络应用程 ...
- Cisco Router WEB管理
目前市场上很多思科路由器或者交换机都可以通过WEB方式配置.尽管很多功能还是只能通过CLI配置,但是一些功能还是很有用的,例如端口的流量监控功能 前期准备: 一.设备的IOS要支持WEB管理功能 ...
- 使用Vert.x构建Web服务器和消息系统
如果你对Node.js感兴趣,Vert.x可能是你的下一个大事件:一个建立在JVM上一个类似的架构企业制度. 这一部分介绍Vert.x是通过两个动手的例子(基于Vert.x 2.0). 当Node.j ...
- Vert.x学习之 Web Client
Vert.x Web Client 原文档 组件源码 组件示例 中英对照表 Pump:泵(平滑流式数据读入内存的机制,防止一次性将大量数据读入内存导致内存溢出) Response Codec:响应编解 ...
- Vert.x(vertx)发送 HTTP/HTTPS请求
Vert.x Web服务有两种协议,一种是HTTP,另外一种是使用ssl的HTTPS,请求的方式有五种,分别是get.post.put.delete.head.为了简单,服务端主要实现对HTTP协议的 ...
- vert.x框架与tomcat的关系
1.前言 大学4年,老师唯一让我们学习的web服务器是tomcat,配置方式是先从官网下载阿帕奇的tomcat文件,然后在开发平台导入,然后再配置web.xml等文件, 是一个可同步可异步请求的服务器 ...
- Node.js Web 开发框架大全《路由篇》
这篇文章与大家分享优秀的 Node.js 路由(Routers)模块.Node 是一个服务器端 JavaScript 解释器,它将改变服务器应该如何工作的概念.它的目标是帮助程序员构建高度可伸缩的应用 ...
- Vert.x Core 文档手册
Vert.x Core 文档手册 中英对照表 Client:客户端 Server:服务器 Primitive:基本(描述类型) Writing:编写(有些地方译为开发) Fluent:流式的 Reac ...
随机推荐
- 2019中山纪念中学夏令营-Day9[JZOJ](第六次模拟赛)
Begin (题目的排序方式:Unkown其实是按心情排的) 异或:(摘自百度百科) 异或(xor)是一个数学运算符.它应用于逻辑运算.异或的数学符号为“⊕”,计算机符号为“xor”.其运算法则为: ...
- 08_代码块丶继承和final
Day07笔记 课程内容 1.封装 2.静态 3.工具类 4.Arrays工具类 封装 概述 1.封装:隐藏事物的属性和实现细节,对外提供公共的访问方式 2.封装的好处: 隐藏了事物的实现细节 提高了 ...
- Netty学习(五)-DelimiterBasedFrameDecoder
上一节我们说了LineBasedframeDecoder来解决粘包拆包的问题,TCP以流的方式进行数据传输,上层应用协议为了对消息进行区分,一般采用如下4种方式: 消息长度固定,累计读取到消息长度总和 ...
- 洛谷 P4344 [SHOI2015]脑洞治疗仪
题意简述 维护序列,支持以下操作: 0 l r:将l~r赋为0 1 l1 r1 l2 r2:将l1~r1中的1替换l2~r2中的0,多余舍弃 2 l r:询问l~r中最大连续1的长度 题解思路 珂朵莉 ...
- 洛谷 P2157 [SDOI2009]学校食堂
题意简述 每个人有一个口味,食堂每次只能为一个人做菜 做每道菜所需的时间是和前一道菜有关的,若前一道菜的对应的口味是a,这一道为b,则做这道菜所需的时间为a 异或 b 每个人都有一个容忍度,最多允许紧 ...
- luoguP3588_[POI2015]PUS
题意 有一个\(n\)个数的序列,已知其中的\(k\)个数,然后有\(m\)个信息,每个信息给出区间\([l,r]\),和\(k\)个数,表示区间\([l,r]\)中这\(k\)个数大于剩下的\(r- ...
- @Validated和@Valid区别
注解地方 @Validated:可以用在类型.方法和方法参数上.但是不能用在成员属性(字段)上 @Valid:可以用在方法.构造函数.方法参数和成员属性(字段)上 两者是否能用于成员属性(字段)上直接 ...
- 记:使用vue全家桶 + vux组件库 打包成 dcloud 5+ app 开发过程中遇到的问题
vue-cli 版本:2.9.6 webpack 版本:3.6.0 1. vue-cli 安装好之后,不是自动打开默认浏览器 在 config文件夹 ---> dev选项中,有个 autoO ...
- CSS 锚点 :target属性 制作选项卡
.pic img:first-of-type{display: block;} .pic img:target{display: block;}
- MySql基础架构以及SQL语句执行流程
01. mysql基础架构 SQL语句是如何执行的 学习一下mysql的基础架构,从一条sql语句是如何执行的来学习. 一般我们写一条查询语句类似下面这样: select user,password ...