Vert.x学习笔记
文章目录
- 一、概述
- 1、官网
- 二、vertx-core
- 0、导包
- 1、hello world
- 2、Verticle
- (1)参考
- (2)示例
- 3、eventBus事件总线
- (1)hello world
- (2)消费确认回复
- 4、Json处理
- (1)常用方法
- (2)不确定类型转换
- 5、Buffer操作
- 6、TCP客户端与服务端
- (1)demo
- 7、Http客户端与服务端
- 三、vertx-web
- 0、导包
- 1、使用
- 【重磅推荐!免费简单内网穿透神器!支持linux+windows】
一、概述
1、官网
https://vertx.io/
二、vertx-core
0、导包
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-core</artifactId>
<version>4.5.10</version>
</dependency>
1、hello world
package com.vertx;
import io.vertx.core.AsyncResult;
import io.vertx.core.Future;
import io.vertx.core.Vertx;
import io.vertx.core.VertxOptions;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.file.FileProps;
import io.vertx.core.file.FileSystem;
import java.util.concurrent.CompletableFuture;
public class Test {
public static void main(String[] args) {
// 创建一个Vertx实例
VertxOptions options = new VertxOptions()
.setWorkerPoolSize(40);
Vertx vertx = Vertx.vertx(options);
// 每秒执行一次
vertx.setPeriodic(1000, id -> {
System.out.println("timer fired!");
});
// 完全都是异步的,
FileSystem fs = vertx.fileSystem();
Future<FileProps> future = fs.props("D:\\example.db");
future.onComplete((AsyncResult<FileProps> ar) -> {
if (ar.succeeded()) {
FileProps props = ar.result();
System.out.println("File size = " + props.size());
} else {
System.out.println("Failure: " + ar.cause().getMessage());
}
});
// 操作链
Future<Void> future2 = fs
.createFile("D:\\foo")
.compose(v -> {
// 当文件foo创建完之后执行,同时返回一个Future
return fs.writeFile("D:\\foo", Buffer.buffer());
})
.compose(v -> {
// 当文件foo创建完之后执行,同时返回一个Future
return fs.move("D:\\foo", "D:\\bar");
});
// 所有都成功
Future.all(future, future2).onComplete(ar -> {
if (ar.succeeded()) {
// All servers started
} else {
// At least one server failed
}
});
// CompletableFuture与Vertx的Future可以转换
CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {});
Future.fromCompletionStage(voidCompletableFuture, vertx.getOrCreateContext())
.onSuccess(str -> {
System.out.println("We have a result: " + str);
})
.onFailure(err -> {
System.err.println("We have a problem");
err.printStackTrace();
});
// 互相转换
future.toCompletionStage().whenComplete((r, t) -> {});
}
}
2、Verticle
(1)参考
https://blog.csdn.net/zhangzehai2234/article/details/134215914
(2)示例
import io.vertx.core.AbstractVerticle;
public class BaseVerticle extends AbstractVerticle {
@Override
public void start() {
System.out.println(("Start"));
}
@Override
public void stop() {
System.out.println(("Stop"));
}
}
import io.vertx.core.AbstractVerticle;
public class MyVerticle extends AbstractVerticle {
@Override
public void start() {
long delay = 1000;
for (int i = 0; i < 50; i++) {
vertx.setTimer(delay, id -> deploy()); // 每隔1秒部署一个 BaseVerticle 实例
delay = delay + 1000;
}
}
private void deploy() {
vertx.deployVerticle(new BaseVerticle(), ar -> { // vertx中的Vertcle的部署是一个异步的操作,所以这里使用带异步结果的异步方法来进行部署,部署成功会生成一个唯一的Verticle ID
if (ar.succeeded()) {
String id = ar.result();
System.out.println(("Successfully deployed " + id));
vertx.setTimer(5000, tid -> undeployLater(id)); // Verticle部署成功5秒以后就卸载该实例
} else {
System.out.println(("Error while deploying" + ar.cause()));
}
});
}
private void undeployLater(String id) {
vertx.undeploy(id, ar -> { //卸载的过程和部署的过程类似,也是一个异步的操作
if (ar.succeeded()) {
System.out.println(("{} was undeployed" + id));
} else {
System.out.println(("{} could not be undeployed" + id));
}
});
}
}
import io.vertx.core.Vertx;
public class Test {
public static void main(String[] args) {
Vertx vertx = Vertx.vertx();
vertx.deployVerticle(new MyVerticle());
}
}
3、eventBus事件总线
(1)hello world
import io.vertx.core.Vertx;
import io.vertx.core.eventbus.DeliveryOptions;
import io.vertx.core.eventbus.EventBus;
import io.vertx.core.eventbus.MessageConsumer;
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
// 创建一个Vertx实例
Vertx vertx = Vertx.vertx();
// 一个vertx有一个eventBus实例
EventBus eventBus = vertx.eventBus();
// 创建一个消费者,address + message,也可以简写 eb.consumer("news.uk.sport", message -> {})
MessageConsumer<Object> consumer = eventBus.consumer("VERTX://MY/TEST");
consumer.handler(message -> {
System.out.println("message: " + message.body());
});
// consumer.unregister(); // 取消注册
eventBus.consumer("VERTX://MY/TEST", message -> {
System.out.println("message2: " + message.body());
});
// 指定address就可以发送事件消息,所有注册这个地址的消费者都会收到该消息
eventBus.publish("VERTX://MY/TEST", "hello world");
// 只收到一次,相当于消费者做了负载均衡,可以发送任意Object类型
eventBus.send("VERTX://MY/TEST", "hello world2");
eventBus.send("VERTX://MY/TEST", "hello world3");
eventBus.send("VERTX://MY/TEST", Arrays.asList("hello world4", "hello world5"));
// 可以设置header,消费者也可以接收header
// DeliveryOptions options = new DeliveryOptions();
// options.addHeader("some-header", "some-value");
// eventBus.send("VERTX://MY/TEST", "Yay! Someone kicked a ball", options);
}
}
(2)消费确认回复
import io.vertx.core.Vertx;
import io.vertx.core.eventbus.EventBus;
import io.vertx.core.eventbus.MessageConsumer;
public class Test {
public static void main(String[] args) {
// 创建一个Vertx实例
Vertx vertx = Vertx.vertx();
// 一个vertx有一个eventBus实例
EventBus eventBus = vertx.eventBus();
MessageConsumer<String> consumer = eventBus.consumer("news.uk.sport");
consumer.handler(message -> {
System.out.println("收到消息: " + message.body());
// 消费回复
message.reply("我处理完消息了");
});
eventBus
.request("news.uk.sport", "我发送了一条消息")
.onComplete(ar -> {
// 判断是否消费成功,消费者调用reply之后会调用
if (ar.succeeded()) {
System.out.println("消费成功: " + ar.result().body());
}
});
}
}
4、Json处理
(1)常用方法
Json处理默认是用的Jackson库,更详细的操作可以查阅Jackson库的操作。
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import java.util.HashMap;
import java.util.Map;
public class Test {
static class User {
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public static void main(String[] args) {
String jsonString = "{\"foo\":\"bar\"}";
// 字符串转json对象
JsonObject object = new JsonObject(jsonString);
// 根据key取值
System.out.println(object.getString("foo"));
//String val = object.getString("some-key");
//int intVal = object.getInteger("some-other-key");
// 根据map生成JsonObject对象
Map<String, Object> map = new HashMap<>();
map.put("foo", "bar");
map.put("xyz", 3);
JsonObject object2 = new JsonObject(map);
// 可以手动放key-value
JsonObject object3 = new JsonObject();
object3.put("foo", "bar").put("num", 123).put("mybool", true);
// 转成实体类
JsonObject objectUser = new JsonObject();
objectUser.put("id", "123").put("name", "zhangsan");
User user = objectUser.mapTo(User.class);
System.out.println(user.getId());
// 实体类转JsonObject
JsonObject jsonObjectMapFrom = JsonObject.mapFrom(user);
System.out.println(jsonObjectMapFrom.getString("id"));
// 数组操作
JsonArray jsonArray = new JsonArray();
jsonArray.add("foo").add(123).add(false);
// 字符串转json数组
String jsonArrayString = "[\"foo\",\"bar\"]";
JsonArray array = new JsonArray(jsonArrayString);
// 从数组取值
String val = array.getString(0);
Integer intVal = array.getInteger(1);
Boolean boolVal = array.getBoolean(2);
}
}
(2)不确定类型转换
可以使用Json.decodeValue
转换为Object之后,再进行类型判断。
// 不确定的类型转换
Object indeterminacyObject = Json.decodeValue("arbitraryJson");
if (indeterminacyObject instanceof JsonObject) {
// That's a valid json object
} else if (indeterminacyObject instanceof JsonArray) {
// That's a valid json array
} else if (indeterminacyObject instanceof String) {
// That's valid string
} else {
// etc...
}
5、Buffer操作
import io.vertx.core.buffer.Buffer;
public class BufferTest {
public static void main(String[] args) {
// 创建空buffer,并指定缓冲区大小
Buffer buff = Buffer.buffer(1000);
// 根据字符串创建buffer,默认utf-8
Buffer buff2 = Buffer.buffer("some string");
// 指定编码格式
Buffer buff3 = Buffer.buffer("some string", "UTF-16");
// 从byte数组创建Buffer
byte[] bytes = new byte[] {1, 3, 5};
Buffer buff4 = Buffer.buffer(bytes);
// 追加buffer
buff.appendInt(123).appendString("hello\n");
socket.write(buff);
// 指定索引写入数据
buff.setInt(1000, 123);
buff.setString(0, "hello");
// 读取Buffer
for (int i = 0; i < buff.length(); i += 4) {
System.out.println("int value at " + i + " is " + buff.getInt(i));
}
int pos = 15;
buff.setUnsignedByte(pos, (short) 200);
System.out.println(buff.getUnsignedByte(pos));
// 获取缓冲区长度,缓冲区的长度是缓冲区中索引最大的字节的索引+ 1。
System.out.println(buff.length());
}
}
6、TCP客户端与服务端
TCP支持限流、SSL等高级操作。
(1)demo
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.net.NetServer;
import io.vertx.core.net.NetServerOptions;
public class ServerTest {
public static void main(String[] args) {
Vertx vertx = Vertx.vertx();
// 创建TCP服务端,进行部分设置
NetServerOptions options = new NetServerOptions()
.setPort(8000);
NetServer server = vertx.createNetServer(options);
// 客户端连接
server.connectHandler(socket -> {
// 客户端连接成功会调用
System.out.println("连接成功");
// 连接关闭
socket.closeHandler(v -> {
System.out.println("连接关闭");
});
});
// 数据接收和写出
server.connectHandler(socket -> {
socket.handler(buffer -> {
// 数据接收的操作,需要用Buffer进行操作
System.out.println("I received some bytes: " + buffer.length());
// 数据写出,都是异步操作
Buffer writeBuffer = Buffer.buffer().appendFloat(12.34f).appendInt(123);
socket.write(writeBuffer);
// 默认UTF-8编码
socket.write("some data");
// 使用指定的编码编写字符串
socket.write("some data", "UTF-16");
// 直接发送文件,零拷贝
//socket.sendFile("myfile.dat");
});
});
// 开始监听
server.listen();
// 可以监听指定主机
// server.listen(1234, "localhost");
// 如果将0用作监听端口,服务器将找到一个未使用的随机端口进行监听。要找出服务器监听的真正端口,可以调用actualPort。
// server
// .listen(0, "localhost")
// .onComplete(res -> {
// if (res.succeeded()) {
// System.out.println("Server is now listening on actual port: " + server.actualPort());
// } else {
// System.out.println("Failed to bind!");
// }
// });
// 关闭服务器
// server
// .close()
// .onComplete(res -> {
// if (res.succeeded()) {
// System.out.println("Server is now closed");
// } else {
// System.out.println("close failed");
// }
// });
}
}
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.net.*;
public class ClientTest {
public static void main(String[] args) {
Vertx vertx = Vertx.vertx();
// 创建TCP服务端,进行部分设置
NetClientOptions options = new NetClientOptions()
.setConnectTimeout(10000).
// 设置重连
setReconnectAttempts(10).
setReconnectInterval(500);
NetClient client = vertx.createNetClient(options);
client
.connect(8000, "localhost")
.onComplete(res -> {
if (res.succeeded()) {
System.out.println("连接成功!");
NetSocket socket = res.result();
// 发送数据
socket.write("some data client");
// 接收数据
socket.handler(buffer -> {
// 数据接收的操作,需要用Buffer进行操作
System.out.println("client received some bytes: " + buffer.length());
});
} else {
System.out.println("连接失败: " + res.cause().getMessage());
}
});
}
}
7、Http客户端与服务端
看到https://vertx.io/docs/vertx-core/java/#_verticles
三、vertx-web
0、导包
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web</artifactId>
<version>4.5.10</version>
</dependency>
1、使用
https://vertx.io/docs/vertx-web/java/
vertx使用起来或许性能会强一些?但是终归生态不如springboot的,用起来还是挺麻烦
【重磅推荐!免费简单内网穿透神器!支持linux+windows】
推荐内网穿透神器【cpolar】https://www.cpolar.com/
点击【免费注册】之后,输入自己的个人信息就可以注册一个账号啦!
本地web项目如何使用外网访问?教你轻松使用cpolar在windows搭建内网穿透
linux虚拟机部署的web项目如何使用外网访问?教你轻松使用cpolar在centos搭建内网穿透
linux虚拟机部署的MySQL如何使用外网访问?教你轻松使用cpolar在centos搭建内网穿透