EclipseVert.x是事件驱动和非阻塞的。这意味着您的应用程序可以使用少量的内核线程处理大量并发。Vert.x让你的应用程序可以用最少的硬件扩展,Vert.x与多种语言一起使用,包括Java、Kotlin、JavaScript、Groovy、Ruby和Scala。
技术无好坏,只有适合不适合.
Vertx,是一个基于JVM、轻量级、高性能的应用平台,非常适用于移动端后台、互联网、企业应用架构。
Vertx,基于Netty全异步通信,并扩展出了很多有用的特性。
Vertx,是基于事件总线设计的高性能架构,保证应用中不同部分以一种非堵塞的线程安全方式通讯。
Vertx,是借鉴Erlang和Akka架构设计,能充分利用多核处理器性能并实现高并发编程需求的框架。
Vertx特点:
支持多种编程语言
目前支持Java、JavaScript、Ruby、Python、Groovy、Clojure、Ceylon等,并提供友好的API接口。以上技术栈的工程师可以非常容易的学习和使用Vert.x 架构。
异步无锁编程
经典的多线程编程模型能满足很多Web开发场景,但随着移动互联网并发连接数的猛增,多线程并发控制模型性能难以扩展,同时要想控制好并发锁需要较高的技巧,目前Reactor异步编程模型开始跑马圈地,而Vert.x就是这种异步无锁编程的一个首选。
对各种IO的丰富支持
目前Vert.x的异步模型已支持TCP、UDP、FileSystem、DNS、EventBus、Sockjs等,基本满足绝大多数系统架构需求。
分布式消息传输
Vert.x基于分布式Bus消息机制实现其Actor模型,我们的业务逻辑如果依赖其他Actor则通过Bus简单的将消息发送出去就可以了。EventBus事件总线,可以轻松编写分布式解耦的程序,具有很好的扩展性。
EventBus也是Vert.x架构的灵魂所在。
生态体系日趋成熟
Vertx归入Eclipse基金会门下,异步驱动已经支持了Postgres、MySQL、MongoDB、Redis等常用组件,并且有若干Vertx在生产环境中的应用案例。
Vertx是轻量级的
vertx的核心代码包只有650kB左右,同时提供丰富的扩展插件,满足各类需求。
模块化
Vertx本身内置强大的模块管理机制,当你写完一个Vert.x业务逻辑的时候,你可以将其打包成module,然后部署到基于Maven的仓库里,与现有主流的开发过程无缝结合。
支持WebSocket
支持WebSocket协议兼容SockJS , 可以非常方便的实现web前端和服务后端长连接通信,是轻量级web聊天室应用首选解决方案。
使用简单
这里的简单意味着你编写的代码是完全基于异步事件的,类似Node.JS,与此同时.你不需要关注线程上的同步,与锁之类的概念,所有的程序都是异步执行并且通信是无阻塞的。
良好的扩展性
因为基于Actor模型,所以你的程序都是一个点一个点的单独在跑,一群点可以组成一个服务,某个点都是可以水平扩展,动态替换,这样你的程序,基本就可以达到无限制的水平扩展。
高并发性
vert.x是一个事件驱动非阻塞的异步编程框架,你可以在极少的核心线程里占用最小限度的硬件资源处理大量的高并发请求。
基本概念
handler: 事件处理器
event loop:事件循环(线程)(同netty)
verticle: Vert.x 基本组件,模块。
worker: 工作线程
event bus: 事件总线
我们看下vertx 的java开发流程
import io.vertx.core.AbstractVerticle;
public class Server extends AbstractVerticle {
public void start() {
vertx.createHttpServer().requestHandler(req -> {
req.response()
.putHeader("content-type", "text/plain")
.end("Hello from Vert.x!");
}).listen(8080);
}
}
但同时vertx也有他的缺点,就拿vertx-web相比springmvc来说,vertx更加灵活,但同时也需要开发人员weba原生开发有更深刻的了解,包括各种请求返回头的添加,以及各种拦截器,自定义消息转换等的处理,都需要开发人员自行配置,这显然是大部分开发人员所不愿意的,所以导致了vertx目前并不怎么流行,但这些并不影响一个框架本身的魅力.当然还有很多轻量级的web开发框架,jfinal,play等等小众框架.
vertx-web-springmvc 是基于vertx -web 类似springmvc的开发风格的web框架,方便原spring开发人员无缝迁移
springmvc 风格注解介绍
注解 | 用法 |
---|---|
TemplateBody | 类似springmvc的@ ResponseBody标记模板渲染 阻塞执行,配合 VertxTemplateEngine标记 |
ResponseBody | 类似springmvc的 @ResponseBody 标记消息转换 (依赖 MessageConverter)阻塞执行,配合 VertxMessageConverter标记 |
RouteHandler | 类似springmvc的 @Controller |
RouteMapping | 类似springmvc的 @RequestMapping |
Interceptor | vertx 拦截器标记 |
RouterAdvice | 类似springmvc的 @ControllerAdvice |
ExceptionHandler | 类似springmvc的 @ExceptionHandler 异常处理 |
package com.taoyuanx.vertxdemo.withspring.web;
import com.taoyuanx.springmvc.vertx.core.anno.route.ResponseBody;
import com.taoyuanx.springmvc.vertx.core.anno.route.RouteHandler;
import com.taoyuanx.springmvc.vertx.core.anno.route.RouteMapping;
import com.taoyuanx.springmvc.vertx.core.core.template.TemplateBody;
import io.vertx.core.Handler;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
/**
* @author dushitaoyuan
* @date 2020/4/21
*/
@RouteHandler(value = "api")
@Component
public class RouteHandlerDemo {
@RouteMapping(value = "demo", method = HttpMethod.GET)
public Handler<RoutingContext> handle() {
return ctx -> {
ctx.response().end("demo");
System.out.println("demo");
};
}
@RouteMapping(value = "blockDemo", method = HttpMethod.GET, blocked = true)
public Handler<RoutingContext> blockHande() {
return ctx -> {
try {
TimeUnit.SECONDS.sleep(3);
System.out.println("blockDemo");
ctx.response().end("blockDemo");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
};
}
@RouteMapping(value = "jsonMessage", method = HttpMethod.GET)
@ResponseBody
public JsonObject jsonMessage(RoutingContext ctx) {
JsonObject jsonObject=new JsonObject();
jsonObject.put("spring json","json");
return jsonObject;
}
@RouteMapping(value = "template", method = HttpMethod.GET)
@TemplateBody
public String template(RoutingContext ctx,JsonObject dataModel)
{
dataModel.put("hello","dushitaoyuan say hi to you! thymeleaf");
return "index.html";
}
@RouteMapping(value = "template2", method = HttpMethod.GET)
@TemplateBody
public String template2(RoutingContext ctx,JsonObject dataModel)
{
dataModel.put("hello","dushitaoyuan say hi to you! freemarker");
return "index.ftl";
}
}
异常处理
@RouterAdvice
@Component
public class RouteAdviceDemo {
@ExceptionHandler(value = MyException.class)
public Handler<RoutingContext> handle() {
return ctx -> {
MyException failure = (MyException) ctx.failure();
ResponseUtil.responseJson(ctx, 500, new JsonObject().put("errorMsg",failure.getMessage()));
};
}
}
自定义模板引擎
ThymeleafTemplateEngine thymeleafTemplateEngine = ThymeleafTemplateEngine.create(serverConfig.getVertx());
FreeMarkerTemplateEngine freeMarkerTemplateEngine = FreeMarkerTemplateEngine.create(serverConfig.getVertx());
springMvcRouterHandler.registVertxTemplateEngine("myTemplate", "templates/", "html", thymeleafTemplateEngine);
springMvcRouterHandler.registVertxTemplateEngine("myTemplate2", "templates/", "ftl", freeMarkerTemplateEngine);
自定义拦截器
@Interceptor(value = "/api/*")
@Component
public class RouteInterceptorDemo implements IRequestInterceptor, Order {
@Override
public boolean pre(RoutingContext routingContext) {
System.out.println("pre1");
return true;
}
@Override
public boolean after(RoutingContext routingContext) {
/**
* end 后 不执行
*/
System.out.println("after1");
return true;
}
@Override
public int order() {
return 100;
}
}
自定义json解析(默认内置)
@VertxMessageConverter
public class JsonMessageConverter implements MessageConverter {
@Override
public boolean support(Object source) {
return true;
}
@Override
public Handler<RoutingContext> convertTo(Object source) {
return ctx -> {
if (source instanceof JsonObject) {
ResponseUtil.responseJson(ctx, HttpResponseStatus.OK.code(), ((JsonObject) source).encode());
return;
}
ResponseUtil.responseJson(ctx, HttpResponseStatus.OK.code(), JSONUtil.toJsonString(source));
};
}
}
代码仓库地址
官方例子仓库