近年来,移动网络、社交网络和电商的兴起,使各大服务提供商的客户端请求数量激增,传统服务器架构已不堪重负,致使基于事件和异步的解决方案备受追捧,如Nginx、NodeJS。Vert.x框架基于事件和异步,依托于全异步Java服务器Netty,并扩展了很多其他特性,以其轻量、高性能、支持多语言开发而备受开发者青睐。
相较于websocket,vertx使用更为简单(具体可参考vertx官网https://vertx.io/)。
Vert.x是事件驱动的,其处理请求的高性能也是基于其事件机制。Vert.x的事件机制中有几个非常重要的概念:Event Loop、Event Loop Vertical、Worker Vertical、Event Bus、Vert.x Module。
Event Loop:即事件循环,是由Vert.x启动的事件处理线程,也是Vert.x项目对外开放的入口,Vert.x由此接收请求事件。一个Vert.x有一个或多个事件循环线程组成,线程最大数量为主机有效的CPU核数。
Event Loop Vertical:事件的业务处理线程,存在于Event Loop中,用于处理非阻塞短任务。
Worker Vertical : 事件的业务处理线程,用于处理长任务阻塞任务。
Event Bus:即事件总线,是Vert.x事件模型中最核心的部分,所有的事件都经由事件总线进行分发,包括Vertical之间的通信事件。
Vert.x Module : Vert.x项目模块,一个应用通常由多个模块组成,每个模块一般包含多个Vertical。(以上来自百度百科)
首先在pom文件中导入相关依赖:
io.vertx
vertx-core
3.4.2
io.vertx
vertx-web
3.4.2
io.vertx
vertx-web-client
3.4.2
作为vertx最核心的部分,我们一般编写一个类继承AbstractVerticle,然后重新它的start方法。
SockJSHandlerOptions sockjsopt=new SockJSHandlerOptions().setHeartbeatInterval(25000);
//默认25秒,具体查看SockJSHandlerOptions类
SockJSHandler sockJSHandler = SockJSHandler.create(vertx,sockjsopt);
//创建路由规则
Router router=new RouterImpl(vertx);
BridgeOptions opt=new BridgeOptions();
opt.setPingTimeout(100000);//默认10秒,具体查看BridgeOptions类
//设置从客户端发送消息到服务端的地址,根据自己的需要可以创建任意个
opt.addInboundPermitted(new PermittedOptions().setAddress("chat.to.server"));
//解决跨域问题
router.route().handler(CorsHandler.create("*")
.allowedMethod(HttpMethod.GET).allowedMethod(HttpMethod.OPTIONS)
.allowedMethod(HttpMethod.POST).allowedHeader("X-PINGARUNER").allowedHeader("Content-Type"));
router.route().handler(BodyHandler.create().setBodyLimit(-1));
router.route("/eventbus/*").handler(sockJSHandler.bridge(opt,bridgeEvent->{
switch (bridgeEvent.type()) {
case SOCKET_CREATED:
System.out.println(new Date()+":This event will occur when a new SockJS socket is created.");
break;
case SOCKET_IDLE:
System.out.println(new Date()+":This event will occur when SockJS socket is on idle for longer period of time than initially configured.");
break;
case SOCKET_PING:
System.out.println(new Date()+":This event will occur when the last ping timestamp is updated for the SockJS socket.");
break;
case SOCKET_CLOSED:
System.out.println(new Date()+":This event will occur when a SockJS socket is closed.");
break;
case SEND:
System.out.println(new Date()+":This event will occur when a message is attempted to be sent from the client to the server.");
break;
case PUBLISH:
System.out.println(new Date()+":This event will occur when a message is attempted to be published from the client to the server.");
break;
case RECEIVE:
System.out.println(new Date()+":This event will occur when a message is attempted to be delivered from the server to the client.");
break;
case REGISTER:
System.out.println(new Date()+":This event will occur when a client attempts to register a handler.");
break;
case UNREGISTER:
System.out.println(new Date()+":This event will occur when a client attempts to unregister a handler.");
break;
default:
break;
}
//设置为true,可以处理任何在eventbus上的事件
bridgeEvent.complete(true);
}));
JSONObject data = new JSONObject();
//创建一个eventbus,用来数据通讯
EventBus eventBus=vertx.eventBus();
//HttpServerOptions httpopt=new HttpServerOptions().setMaxWebsocketFrameSize(Integer.parseInt(PropertiesUtil.getProperties("common", "maxWebsocketFrameSize")));//设置数据量的大小,在数据量小的时候,这个值可以不用设置
HttpServerOptions httpopt=new HttpServerOptions();//设置数据量的大小,在数据量小的时候,这个值可以不用设置
HttpServer server=vertx.createHttpServer(httpopt);
server.requestHandler(router::accept).listen(8080, res -> {
if (res.succeeded()) {
System.out.println("服务开启成功!");
} else {
System.out.println("服务开启失败");
}
});
//设置数据推送出去的时间限制
DeliveryOptions deliveryOptions=new DeliveryOptions(new JsonObject().put("timeout", 10000));
//注册地址,然后对接收到客户端来的消息进行处理
eventBus.consumer("chat.to.server", message -> {
System.out.println(new Date()+":客户端发往服务端的消息内容为:"+message.body().toString());
eventBus.publish("chat.to.server",data,deliveryOptions);
System.out.println(new Date()+":数据发布出去的时间");
});
//周期性推送数据
vertx.setPeriodic(10000, timerID -> {
eventBus.publish("chat.to.server", ata,deliveryOptions);
System.out.println(new Date()+":推送完毕");
});
}
然后我们在主方法或者Listener中便可对其进行调用,具体如下
Vertx vertx=Vertx.vertx();
//部署verticle
vertx.deployVerticle(PushTrailVerticle.class.getName());
//PushTrailVerticle为你所编写的verticle类
当出现上图时,说明你后台框架已搭建好,接下来补全推送数据即可。
接下来便可编写前端订阅代码:
下载 vertx-eventbus.js文件并引入到你的html中
var ebTrail=new EventBus("http://127.0.0.1:8080/eventbus");
ebTrail.onopen=function(){//监听数据
ebTrail.registerHandler("chat.to.server",function(err,msg){
console.log(msg.body);//在这里对接收的数据进行一些操作
});
ebTrail.publish("chat.to.server","RequestTrailData");//这行代码可以发送信息给服务端
};
想要详细了解vertx的朋友可访问vertx官网:https://vertx.io/