diff --git a/pom.xml b/pom.xml
index 7348362..5f6bd1d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -172,6 +172,11 @@
sf-apijson
${sf.version}
+
+ com.smarterFramework
+ sf-vertx-api
+ ${sf.version}
+
cn.hutool
hutool-core
diff --git a/sf-system/src/main/java/com/sf/system/deployment/controller/DeploymentApplyEnvironmentController.java b/sf-system/src/main/java/com/sf/system/deployment/controller/DeploymentApplyEnvironmentController.java
index c52a34d..59f41e6 100644
--- a/sf-system/src/main/java/com/sf/system/deployment/controller/DeploymentApplyEnvironmentController.java
+++ b/sf-system/src/main/java/com/sf/system/deployment/controller/DeploymentApplyEnvironmentController.java
@@ -1,26 +1,28 @@
-package com.sf.deployment.controller;
+package com.sf.system.deployment.controller;
import java.util.List;
+
import javax.servlet.http.HttpServletResponse;
-import com.sf.system.deployment.domain.DeploymentApplyEnvironment;
-import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
+
import com.sf.common.annotation.Log;
import com.sf.common.core.controller.BaseController;
import com.sf.common.core.domain.AjaxResult;
-import com.sf.common.enums.BusinessType;
-import com.sf.deployment.service.IDeploymentApplyEnvironmentService;
-import com.sf.common.utils.poi.ExcelUtil;
import com.sf.common.core.page.TableDataInfo;
+import com.sf.common.enums.BusinessType;
+import com.sf.common.utils.poi.ExcelUtil;
+import com.sf.system.deployment.domain.DeploymentApplyEnvironment;
+import com.sf.system.deployment.service.IDeploymentApplyEnvironmentService;
/**
* 环境维护Controller
diff --git a/sf-system/src/main/java/com/sf/system/deployment/mapper/DeploymentApplyEnvironmentMapper.java b/sf-system/src/main/java/com/sf/system/deployment/mapper/DeploymentApplyEnvironmentMapper.java
index 905b7cc..195e6ca 100644
--- a/sf-system/src/main/java/com/sf/system/deployment/mapper/DeploymentApplyEnvironmentMapper.java
+++ b/sf-system/src/main/java/com/sf/system/deployment/mapper/DeploymentApplyEnvironmentMapper.java
@@ -1,4 +1,4 @@
-package com.sf.deployment.mapper;
+package com.sf.system.deployment.mapper;
import com.sf.system.deployment.domain.DeploymentApplyEnvironment;
diff --git a/sf-system/src/main/java/com/sf/system/deployment/service/IDeploymentApplyEnvironmentService.java b/sf-system/src/main/java/com/sf/system/deployment/service/IDeploymentApplyEnvironmentService.java
index 3f8d855..bac2f75 100644
--- a/sf-system/src/main/java/com/sf/system/deployment/service/IDeploymentApplyEnvironmentService.java
+++ b/sf-system/src/main/java/com/sf/system/deployment/service/IDeploymentApplyEnvironmentService.java
@@ -1,4 +1,4 @@
-package com.sf.deployment.service;
+package com.sf.system.deployment.service;
import com.sf.system.deployment.domain.DeploymentApplyEnvironment;
diff --git a/sf-system/src/main/java/com/sf/system/deployment/service/impl/DeploymentApplyEnvironmentServiceImpl.java b/sf-system/src/main/java/com/sf/system/deployment/service/impl/DeploymentApplyEnvironmentServiceImpl.java
index 47945cc..d988e0b 100644
--- a/sf-system/src/main/java/com/sf/system/deployment/service/impl/DeploymentApplyEnvironmentServiceImpl.java
+++ b/sf-system/src/main/java/com/sf/system/deployment/service/impl/DeploymentApplyEnvironmentServiceImpl.java
@@ -1,12 +1,14 @@
-package com.sf.deployment.service.impl;
+package com.sf.system.deployment.service.impl;
import java.util.List;
-import com.sf.common.utils.DateUtils;
-import com.sf.system.deployment.domain.DeploymentApplyEnvironment;
+
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
-import com.sf.deployment.mapper.DeploymentApplyEnvironmentMapper;
-import com.sf.deployment.service.IDeploymentApplyEnvironmentService;
+
+import com.sf.common.utils.DateUtils;
+import com.sf.system.deployment.domain.DeploymentApplyEnvironment;
+import com.sf.system.deployment.mapper.DeploymentApplyEnvironmentMapper;
+import com.sf.system.deployment.service.IDeploymentApplyEnvironmentService;
/**
* 环境维护Service业务层处理
diff --git a/sf-vertx-api/pom.xml b/sf-vertx-api/pom.xml
index 4b01f87..1269d58 100644
--- a/sf-vertx-api/pom.xml
+++ b/sf-vertx-api/pom.xml
@@ -19,21 +19,23 @@
lombok
provided
+
+
+ com.alibaba.fastjson2
+ fastjson2
+
org.apache.maven.plugins
- maven-war-plugin
- 3.1.0
+ maven-compiler-plugin
- false
- ${project.artifactId}
+ 1.8
+ 1.8
- ${project.artifactId}
-
\ No newline at end of file
diff --git a/sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/AppConfig.java b/sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/AppConfig.java
index 70319e6..9ce8261 100644
--- a/sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/AppConfig.java
+++ b/sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/AppConfig.java
@@ -8,7 +8,8 @@ import lombok.Data;
@Data
public class AppConfig implements Serializable {
private static final long serialVersionUID = 1518165296680157119L;
+ private String appCode;
private boolean exclusiveService; // 预留字段, 独立端口
- private List serverAddressList;
-
+ private List nodeList;
+ private List strategyList;
}
diff --git a/sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/DataSecurity.java b/sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/DataSecurity.java
new file mode 100644
index 0000000..c52af2e
--- /dev/null
+++ b/sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/DataSecurity.java
@@ -0,0 +1,13 @@
+package com.sf.vertx.api.pojo;
+
+import java.io.Serializable;
+
+import lombok.Data;
+
+@Data
+public class DataSecurity implements Serializable {
+ private static final long serialVersionUID = 5034274428665340830L;
+ private String algorithm; // 国密加解密
+ private String publicKey; // 公钥
+ private String privateKey; // 私钥
+}
diff --git a/sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/GatewayInterface.java b/sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/GatewayInterface.java
new file mode 100644
index 0000000..6c47fc9
--- /dev/null
+++ b/sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/GatewayInterface.java
@@ -0,0 +1,12 @@
+package com.sf.vertx.api.pojo;
+
+import java.io.Serializable;
+
+import lombok.Data;
+
+@Data
+public class GatewayInterface implements Serializable {
+ private static final long serialVersionUID = -313734935498432381L;
+ private String uri;
+ private String method; // 大写
+}
diff --git a/sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/HttpClientOptionsConfig.java b/sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/HttpClientOptionsConfig.java
new file mode 100644
index 0000000..20aa4ae
--- /dev/null
+++ b/sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/HttpClientOptionsConfig.java
@@ -0,0 +1,14 @@
+package com.sf.vertx.api.pojo;
+
+import java.io.Serializable;
+
+import lombok.Data;
+
+@Data
+public class HttpClientOptionsConfig implements Serializable {
+ private static final long serialVersionUID = -6302301564759941097L;
+ private int maxPoolSize;
+ private int connectTimeout;
+ private int http2KeepAliveTimeout;
+ private int idleTimeout;
+}
diff --git a/sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/Node.java b/sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/Node.java
new file mode 100644
index 0000000..a06af7e
--- /dev/null
+++ b/sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/Node.java
@@ -0,0 +1,110 @@
+package com.sf.vertx.api.pojo;
+
+import java.io.Serializable;
+
+import com.alibaba.fastjson2.annotation.JSONField;
+
+import lombok.Data;
+
+/**
+ * String ip:负载IP
+ * final Integer weight:权重,保存配置的权重
+ * Integer effectiveWeight:有效权重,轮询的过程权重可能变化
+ * Integer currentWeight:当前权重,比对该值大小获取节点
+ * 第一次加权轮询时:currentWeight = weight = effectiveWeight
+ * 后面每次加权轮询时:currentWeight 的值都会不断变化,其他权重不变
+ */
+public class Node implements Comparable, Serializable {
+ private static final long serialVersionUID = -2846988871213226377L;
+ private String ip;
+ private Integer port;
+ private Integer weight;
+ private Integer effectiveWeight;
+ private Integer currentWeight;
+ private boolean createHttp; // 协议
+ private boolean createHttps;
+
+ public Node() {
+ }
+
+ public Node(String ip, Integer weight) {
+ this.ip = ip;
+ this.weight = weight;
+ this.effectiveWeight = weight;
+ this.currentWeight = weight;
+ }
+
+ public Node(String ip, Integer weight, Integer effectiveWeight, Integer currentWeight) {
+ this.ip = ip;
+ this.weight = weight;
+ this.effectiveWeight = effectiveWeight;
+ this.currentWeight = currentWeight;
+ }
+
+ public boolean isCreateHttp() {
+ return createHttp;
+ }
+
+ public void setCreateHttp(boolean createHttp) {
+ this.createHttp = createHttp;
+ }
+
+ public boolean isCreateHttps() {
+ return createHttps;
+ }
+
+ public void setCreateHttps(boolean createHttps) {
+ this.createHttps = createHttps;
+ }
+
+ public String getIp() {
+ return ip;
+ }
+
+ public void setIp(String ip) {
+ this.ip = ip;
+ }
+
+ public Integer getPort() {
+ return port;
+ }
+
+ public void setPort(Integer port) {
+ this.port = port;
+ }
+
+ public Integer getWeight() {
+ return weight;
+ }
+
+ public void setWeight(Integer weight) {
+ this.weight = weight;
+ }
+
+ public Integer getEffectiveWeight() {
+ return effectiveWeight;
+ }
+
+ public void setEffectiveWeight(Integer effectiveWeight) {
+ this.effectiveWeight = effectiveWeight;
+ }
+
+ public Integer getCurrentWeight() {
+ return currentWeight;
+ }
+
+ public void setCurrentWeight(Integer currentWeight) {
+ this.currentWeight = currentWeight;
+ }
+
+ @Override
+ public int compareTo(Node node) {
+ return currentWeight > node.currentWeight ? 1 : (currentWeight.equals(node.currentWeight) ? 0 : -1);
+ }
+
+ @Override
+ public String toString() {
+ return "{ip='" + ip + "', weight=" + weight + ", effectiveWeight=" + effectiveWeight + ", currentWeight="
+ + currentWeight + "}";
+ }
+}
diff --git a/sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/ServerAddress.java b/sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/ServerAddress.java
index d94bcc2..ce814a2 100644
--- a/sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/ServerAddress.java
+++ b/sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/ServerAddress.java
@@ -1,14 +1,14 @@
-package com.sf.vertx.api.pojo;
-
-import java.io.Serializable;
-
-import lombok.Data;
-
-@Data
-public class ServerAddress implements Serializable {
- private static final long serialVersionUID = 2821255113510132943L;
- private boolean createHttp; // 协议
- private boolean createHttps;
- private String ip;
- private int port;
-}
+//package com.sf.vertx.api.pojo;
+//
+//import java.io.Serializable;
+//
+//import lombok.Data;
+//
+//@Data
+//public class ServerAddress implements Serializable {
+// private static final long serialVersionUID = 2821255113510132943L;
+// private boolean createHttp; // 协议
+// private boolean createHttps;
+// private String ip;
+// private int port;
+//}
diff --git a/sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/Strategy.java b/sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/Strategy.java
index 49f8a1c..3897aa5 100644
--- a/sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/Strategy.java
+++ b/sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/Strategy.java
@@ -1,14 +1,21 @@
package com.sf.vertx.api.pojo;
import java.io.Serializable;
+import java.util.List;
+
+import lombok.Data;
/***
* 策略
* @author xy
*
*/
+@Data
public class Strategy implements Serializable {
private static final long serialVersionUID = -8831406773224882471L;
+ private DataSecurity dataSecurity;
+ private List gatewayInterfaceList;
+ private HttpClientOptionsConfig httpClientOptionsConfig; // 高并发情况,配置接口连接池
}
diff --git a/sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/VertxConfig.java b/sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/VertxConfig.java
new file mode 100644
index 0000000..9a50994
--- /dev/null
+++ b/sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/VertxConfig.java
@@ -0,0 +1,13 @@
+package com.sf.vertx.api.pojo;
+
+import java.io.Serializable;
+
+import lombok.Data;
+
+@Data
+public class VertxConfig implements Serializable {
+ private static final long serialVersionUID = -1706421732809219829L;
+ private Integer port; // 启动端口
+ private VertxOptionsConfig vertxOptionsConfig;
+
+}
diff --git a/sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/VertxOptionsConfig.java b/sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/VertxOptionsConfig.java
new file mode 100644
index 0000000..efe4dc5
--- /dev/null
+++ b/sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/VertxOptionsConfig.java
@@ -0,0 +1,27 @@
+package com.sf.vertx.api.pojo;
+
+import java.util.concurrent.TimeUnit;
+
+import lombok.Data;
+
+@Data
+public class VertxOptionsConfig {
+ private int eventLoopPoolSize;
+ private int workerPoolSize ;
+ private int internalBlockingPoolSize;
+ private long blockedThreadCheckInterval;
+ private long maxEventLoopExecuteTime;
+ private long maxWorkerExecuteTime;
+ //private ClusterManager clusterManager;
+ private boolean haEnabled;
+ private int quorumSize;
+ private String haGroup;
+ private long warningExceptionTime;
+ private boolean preferNativeTransport;
+ private TimeUnit maxEventLoopExecuteTimeUnit;
+ private TimeUnit maxWorkerExecuteTimeUnit;
+ private TimeUnit warningExceptionTimeUnit;
+ private TimeUnit blockedThreadCheckIntervalUnit;
+ private boolean disableTCCL;
+ private Boolean useDaemonThread;
+}
diff --git a/sf-vertx-api/src/main/java/com/sf/vertx/arithmetic/roundRobin/SacLoadBalancing.java b/sf-vertx-api/src/main/java/com/sf/vertx/arithmetic/roundRobin/SacLoadBalancing.java
new file mode 100644
index 0000000..e8fe95e
--- /dev/null
+++ b/sf-vertx-api/src/main/java/com/sf/vertx/arithmetic/roundRobin/SacLoadBalancing.java
@@ -0,0 +1,7 @@
+package com.sf.vertx.arithmetic.roundRobin;
+
+import com.sf.vertx.api.pojo.Node;
+
+public interface SacLoadBalancing {
+ Node selectNode();
+}
diff --git a/sf-vertx-api/src/main/java/com/sf/vertx/arithmetic/roundRobin/WeightedRoundRobin.java b/sf-vertx-api/src/main/java/com/sf/vertx/arithmetic/roundRobin/WeightedRoundRobin.java
new file mode 100644
index 0000000..377a3ac
--- /dev/null
+++ b/sf-vertx-api/src/main/java/com/sf/vertx/arithmetic/roundRobin/WeightedRoundRobin.java
@@ -0,0 +1,109 @@
+package com.sf.vertx.arithmetic.roundRobin;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.sf.vertx.api.pojo.Node;
+
+/**
+ * 加权轮询算法
+ * https://www.cnblogs.com/dennyLee2025/p/16128477.html
+ */
+public class WeightedRoundRobin implements SacLoadBalancing {
+
+ private static List nodes = new ArrayList<>();
+ // 权重之和
+ public static Integer totalWeight = 0;
+ // 准备模拟数据
+// static {
+// nodes.add(new Node("192.168.1.101", 1));
+// nodes.add(new Node("192.168.1.102", 3));
+// nodes.add(new Node("192.168.1.103", 2));
+// nodes.forEach(node -> totalWeight += node.getEffectiveWeight());
+// }
+
+ public void init(List serverAddressList) {
+ nodes = serverAddressList;
+ nodes.forEach(node -> totalWeight += node.getEffectiveWeight());
+ }
+
+ /**
+ * 按照当前权重(currentWeight)最大值获取IP
+ *
+ * @return Node
+ */
+ public Node selectNode() {
+ if (nodes == null || nodes.size() <= 0)
+ return null;
+ if (nodes.size() == 1)
+ return nodes.get(0);
+
+ Node nodeOfMaxWeight = null; // 保存轮询选中的节点信息
+// 之前写错的代码
+// synchronized (nodes){
+ synchronized (WeightedRoundRobin.class) {
+ // 打印信息对象:避免并发时打印出来的信息太乱,不利于观看结果
+ StringBuffer sb = new StringBuffer();
+ sb.append(Thread.currentThread().getName() + "==加权轮询--[当前权重]值的变化:" + printCurrentWeight(nodes));
+
+ // 选出当前权重最大的节点
+ Node tempNodeOfMaxWeight = null;
+ for (Node node : nodes) {
+ if (tempNodeOfMaxWeight == null)
+ tempNodeOfMaxWeight = node;
+ else
+ tempNodeOfMaxWeight = tempNodeOfMaxWeight.compareTo(node) > 0 ? tempNodeOfMaxWeight : node;
+ }
+ // 必须new个新的节点实例来保存信息,否则引用指向同一个堆实例,后面的set操作将会修改节点信息
+ nodeOfMaxWeight = new Node(tempNodeOfMaxWeight.getIp(), tempNodeOfMaxWeight.getWeight(),
+ tempNodeOfMaxWeight.getEffectiveWeight(), tempNodeOfMaxWeight.getCurrentWeight());
+ nodeOfMaxWeight.setCreateHttp(tempNodeOfMaxWeight.isCreateHttp());
+ nodeOfMaxWeight.setCreateHttps(tempNodeOfMaxWeight.isCreateHttps());
+ nodeOfMaxWeight.setPort(tempNodeOfMaxWeight.getPort());
+ // 调整当前权重比:按权重(effectiveWeight)的比例进行调整,确保请求分发合理。
+ tempNodeOfMaxWeight.setCurrentWeight(tempNodeOfMaxWeight.getCurrentWeight() - totalWeight);
+ sb.append(" -> " + printCurrentWeight(nodes));
+
+ nodes.forEach(node -> node.setCurrentWeight(node.getCurrentWeight() + node.getEffectiveWeight()));
+
+ sb.append(" -> " + printCurrentWeight(nodes));
+ System.out.println(sb); // 打印权重变化过程
+ }
+ return nodeOfMaxWeight;
+ }
+
+ // 格式化打印信息
+ private String printCurrentWeight(List nodes) {
+ StringBuffer stringBuffer = new StringBuffer("[");
+ nodes.forEach(node -> stringBuffer.append(node.getCurrentWeight() + ","));
+ return stringBuffer.substring(0, stringBuffer.length() - 1) + "]";
+ }
+
+ // 并发测试:两个线程循环获取节点
+ public static void main(String[] args) {
+ List serverAddressList = new ArrayList<>();
+ Node node1 = new Node("192.168.1.101", 1);
+ serverAddressList.add(node1);
+ Node node2 = new Node("192.168.1.102", 3);
+ serverAddressList.add(node2);
+
+ Node node3 = new Node("192.168.1.103", 2);
+ serverAddressList.add(node3);
+ Thread thread = new Thread(() -> {
+ WeightedRoundRobin weightedRoundRobin1 = new WeightedRoundRobin();
+ weightedRoundRobin1.init(serverAddressList);
+ for (int i = 1; i <= totalWeight; i++) {
+ Node node = weightedRoundRobin1.selectNode();
+ System.out.println(Thread.currentThread().getName() + "==第" + i + "次轮询选中[当前权重最大]的节点:" + node + "\n");
+ }
+ });
+ thread.start();
+ WeightedRoundRobin weightedRoundRobin2 = new WeightedRoundRobin();
+ weightedRoundRobin2.init(serverAddressList);
+ for (int i = 1; i <= totalWeight; i++) {
+ Node node = weightedRoundRobin2.selectNode();
+ System.out.println(Thread.currentThread().getName() + "==第" + i + "次轮询选中[当前权重最大]的节点:" + node + "\n");
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/sf-vertx/pom.xml b/sf-vertx/pom.xml
index c545464..4ea5e87 100644
--- a/sf-vertx/pom.xml
+++ b/sf-vertx/pom.xml
@@ -30,6 +30,10 @@
+
+ com.smarterFramework
+ sf-vertx-api
+
org.springframework.boot
spring-boot-starter-web
@@ -61,6 +65,22 @@
org.apache.commons
commons-pool2
+
+
+ io.vertx
+ vertx-unit
+ test
+
io.vertx
@@ -115,24 +135,23 @@
com.fasterxml.jackson.core
jackson-databind
-
+
- com.alibaba
- fastjson
- 2.0.48
+ com.alibaba.fastjson2
+ fastjson2
-
-
+
+
org.slf4j
slf4j-api
- org.slf4j
- slf4j-simple
- jar
-
+ org.slf4j
+ slf4j-simple
+ jar
+
ch.qos.logback
logback-classic
@@ -147,6 +166,11 @@
org.apache.commons
commons-lang3
+
+ io.netty
+ netty-all
+
+
diff --git a/sf-vertx/src/main/java/com/sf/AdminApplication.java b/sf-vertx/src/main/java/com/sf/AdminApplication.java
index d148318..7e91c8e 100644
--- a/sf-vertx/src/main/java/com/sf/AdminApplication.java
+++ b/sf-vertx/src/main/java/com/sf/AdminApplication.java
@@ -26,6 +26,5 @@ public class AdminApplication {
public static void main(String[] args) throws Exception {
// System.setProperty("spring.devtools.restart.enabled", "false");
APPLICATION_CONTEXT = SpringApplication.run(AdminApplication.class, args);
- log.info("dafafsdfa:{}", "dsafs");
}
}
diff --git a/sf-vertx/src/main/java/com/sf/vertx/constans/RedisConfig.java b/sf-vertx/src/main/java/com/sf/vertx/constans/RedisConfig.java
index 46ea55a..0d731c4 100644
--- a/sf-vertx/src/main/java/com/sf/vertx/constans/RedisConfig.java
+++ b/sf-vertx/src/main/java/com/sf/vertx/constans/RedisConfig.java
@@ -1,5 +1,24 @@
package com.sf.vertx.constans;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+
+@Component
public class RedisConfig {
- public static final String VETX_ENVIRONMENT_KEY = "vertx:config:";
+
+ @Value("${server.vertx.environment}")
+ private String vertxEnvironment;
+
+ public static final String BASE_REDIS_KEY = "vertx:config:";
+ public static String APP_CONFIG_SET_KEY = null;
+ public static String APP_CONFIG_PREFIX_KEY = null;
+ public static String VERTX_CONFIG_STRING_KEY = null;
+
+ public void init() {
+ APP_CONFIG_PREFIX_KEY = BASE_REDIS_KEY + vertxEnvironment;
+ APP_CONFIG_SET_KEY = APP_CONFIG_PREFIX_KEY+":set";
+ VERTX_CONFIG_STRING_KEY = BASE_REDIS_KEY + vertxEnvironment + ":vertx";
+ }
}
+
diff --git a/sf-vertx/src/main/java/com/sf/vertx/controller/AppConfigController.java b/sf-vertx/src/main/java/com/sf/vertx/controller/AppConfigController.java
new file mode 100644
index 0000000..d9309bd
--- /dev/null
+++ b/sf-vertx/src/main/java/com/sf/vertx/controller/AppConfigController.java
@@ -0,0 +1,40 @@
+package com.sf.vertx.controller;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.sf.vertx.api.pojo.AppConfig;
+import com.sf.vertx.service.AppConfigService;
+
+import lombok.extern.slf4j.Slf4j;
+
+/***
+ * 测试redis
+ *
+ * @author xy
+ *
+ */
+@RestController
+@RequestMapping("/vertx/test/redis")
+@Slf4j
+public class AppConfigController {
+ @Autowired
+ private AppConfigService appConfigService;
+
+ @PostMapping("/addAppConfig")
+ public String addAppConfig(@RequestBody AppConfig appConfig) {
+ appConfigService.addAppConfig(appConfig);
+ return null;
+ }
+
+ @PostMapping("/addVertxConfig")
+ public String addVertxConfig() {
+ return null;
+ }
+
+
+
+}
diff --git a/sf-vertx/src/main/java/com/sf/vertx/controller/TestRedisController.java b/sf-vertx/src/main/java/com/sf/vertx/controller/TestRedisController.java
deleted file mode 100644
index 0b948f7..0000000
--- a/sf-vertx/src/main/java/com/sf/vertx/controller/TestRedisController.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.sf.vertx.controller;
-
-import java.util.Set;
-
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.data.redis.core.RedisTemplate;
-import org.springframework.data.redis.core.ZSetOperations;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import com.sf.vertx.constans.RedisConfig;
-
-import lombok.extern.slf4j.Slf4j;
-
-/***
- * 测试redis
- *
- * @author xy
- *
- */
-@RestController
-@RequestMapping("/vertx/test/redis")
-@Slf4j
-public class TestRedisController {
- @Value("${server.vertx.environment}")
- private String vertxEnvironment;
- @Autowired
- private RedisTemplate redisTemplate;
-
- @GetMapping("/test")
- public String test() {
- redisTemplate.opsForValue().set("a", "1");
- return redisTemplate.opsForValue().get("a");
- }
-
- public String allConfig() {
- String setKey = RedisConfig.VETX_ENVIRONMENT_KEY+vertxEnvironment;
- // 获取所有app列表
- Set set = redisTemplate.opsForZSet().range(setKey, 0, -1);
- for(String appCode : set) {
- String appCodeKey = setKey + ":" + appCode;
- String appCodeValue = redisTemplate.opsForValue().get(appCodeKey);
- if(StringUtils.isNotBlank(appCodeValue)) {
-
- }
- }
-
- // 添加zset
- return null;
- }
-}
diff --git a/sf-vertx/src/main/java/com/sf/vertx/init/DynamicBuildServer.java b/sf-vertx/src/main/java/com/sf/vertx/init/DynamicBuildServer.java
index 7849af9..df8118c 100644
--- a/sf-vertx/src/main/java/com/sf/vertx/init/DynamicBuildServer.java
+++ b/sf-vertx/src/main/java/com/sf/vertx/init/DynamicBuildServer.java
@@ -1,36 +1,33 @@
package com.sf.vertx.init;
-import java.util.concurrent.atomic.AtomicReference;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
-import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
-import com.alibaba.fastjson2.JSONObject;
-import com.sf.vertx.security.MainSecurity;
+import com.sf.vertx.api.pojo.AppConfig;
+import com.sf.vertx.api.pojo.Node;
+import com.sf.vertx.api.pojo.VertxConfig;
+import com.sf.vertx.arithmetic.roundRobin.SacLoadBalancing;
+import com.sf.vertx.arithmetic.roundRobin.WeightedRoundRobin;
+import com.sf.vertx.constans.RedisConfig;
+import com.sf.vertx.service.AppConfigService;
-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.http.HttpClient;
-import io.vertx.core.http.HttpClientOptions;
import io.vertx.core.http.HttpServer;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.net.SocketAddress;
import io.vertx.ext.web.Router;
-import io.vertx.ext.web.handler.BodyHandler;
import io.vertx.ext.web.proxy.handler.ProxyHandler;
-import io.vertx.httpproxy.Body;
import io.vertx.httpproxy.HttpProxy;
-import io.vertx.httpproxy.ProxyContext;
-import io.vertx.httpproxy.ProxyInterceptor;
-import io.vertx.httpproxy.ProxyRequest;
-import io.vertx.httpproxy.ProxyResponse;
import lombok.extern.slf4j.Slf4j;
/***
@@ -43,31 +40,91 @@ import lombok.extern.slf4j.Slf4j;
@Order(value = 10)
@Component
public class DynamicBuildServer implements ApplicationRunner {
+ @Value("${server.vertx.server.default.port}")
+ private Integer serverDefaultPort;
+
@Autowired
- private RedisTemplate redisTemplate;
+ private AppConfigService appConfigService;
+
+ @Autowired
+ private RedisConfig redisConfig;
@Override
public void run(ApplicationArguments args) throws Exception {
- appStartLoadData();
-
- // 创建服务
+ // 初始化redis key
+ redisConfig.init();
- // 创建路由
-
- // 创建非加密路由
-
- // 创建加密路由
-
+ // 加载vertx、应用配置
+ appStartLoadData();
}
/***
* 应用启动, 从redis读取配置,初始化vertx服务
*/
private void appStartLoadData() {
- // 数据配置格式
+ // 编解码线程池
+ Vertx VERTX = Vertx.vertx(new VertxOptions().setWorkerPoolSize(20));
+ // 创建HTTP监听
+ HttpServer server = VERTX.createHttpServer();
+ Router mainHttpRouter = Router.router(VERTX);
+ VertxConfig vertxConfig = appConfigService.loadVertxConfig();
+ Integer serverPort = (vertxConfig == null || vertxConfig.getPort() == null) ? serverDefaultPort : vertxConfig.getPort();
+ server.requestHandler(mainHttpRouter).listen(serverPort, h -> {
+ if (h.succeeded()) {
+ log.info("HTTP端口监听成功:{}", serverPort);
+ } else {
+ log.error("HTTP端口监听失败:{}", serverPort);
+ }
+ });
+
+ ConcurrentHashMap cacheAppConfig = appConfigService.loadAllConfig();
+ for (String appCode : cacheAppConfig.keySet()) {
+ AppConfig appConfig = cacheAppConfig.get(appCode);
+ // 负载均衡算法
+ // 轮训
+ SacLoadBalancing sacLoadBalancing = roundRobin(appConfig.getNodeList());
+
+
+ // 有策略
+ if (appConfig.getStrategyList() != null && appConfig.getStrategyList().size() > 0) {
+ } else {
+ // 无策略,直接走反向代理
+// HttpClientOptions clientOptions = new HttpClientOptions();
+// clientOptions.setMaxPoolSize(20); // 最大连接池大小
+// clientOptions.setConnectTimeout(5000); // 连接超时 毫秒
+// clientOptions.setHttp2KeepAliveTimeout(1);
+// clientOptions.setIdleTimeout(1000); // 连接空闲超时 毫秒
+// HttpClient proxyClient = VERTX.createHttpClient(clientOptions);
+
+ HttpClient proxyClient = VERTX.createHttpClient();
+ HttpProxy proxy = HttpProxy.reverseProxy(proxyClient);
+ proxy.originSelector(request -> Future.succeededFuture(resolveOriginAddress(sacLoadBalancing, request)));
+ mainHttpRouter.route().handler(ProxyHandler.create(proxy));
+ }
+ }
+ }
+
+ public SocketAddress resolveOriginAddress(SacLoadBalancing sacLoadBalancing, HttpServerRequest request) {
+ // TODO 区分https、http
+ Node node = sacLoadBalancing.selectNode();
+ SocketAddress socketAddress = SocketAddress.inetSocketAddress(node.getPort(), node.getIp());
+ log.info("负载均衡跳转地址:{}", socketAddress.host() +";"+socketAddress.port());
+ return socketAddress;
}
-
+ private SacLoadBalancing roundRobin(List nodeList) {
+ WeightedRoundRobin weightedRoundRobin = new WeightedRoundRobin();
+ int weight = 1;
+ for(Node node : nodeList) {
+ node.setWeight(weight);
+ node.setCurrentWeight(weight);
+ node.setEffectiveWeight(weight);
+ weight++;
+ WeightedRoundRobin.totalWeight += node.getEffectiveWeight();
+ }
+ weightedRoundRobin.init(nodeList);
+ return weightedRoundRobin;
+ }
}
diff --git a/sf-vertx/src/main/java/com/sf/vertx/service/AppConfigService.java b/sf-vertx/src/main/java/com/sf/vertx/service/AppConfigService.java
new file mode 100644
index 0000000..8664531
--- /dev/null
+++ b/sf-vertx/src/main/java/com/sf/vertx/service/AppConfigService.java
@@ -0,0 +1,18 @@
+package com.sf.vertx.service;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+import com.sf.vertx.api.pojo.AppConfig;
+import com.sf.vertx.api.pojo.VertxConfig;
+
+public interface AppConfigService {
+ ConcurrentHashMap loadAllConfig();
+
+ void addAppConfig(AppConfig appConfig);
+
+ void deleteAppConfig(AppConfig appConfig);
+
+ VertxConfig loadVertxConfig();
+
+ void addVertxConfig(VertxConfig vertxConfig);
+}
diff --git a/sf-vertx/src/main/java/com/sf/vertx/service/config/RedisConfigService.java b/sf-vertx/src/main/java/com/sf/vertx/service/config/RedisConfigService.java
deleted file mode 100644
index 1d9cfda..0000000
--- a/sf-vertx/src/main/java/com/sf/vertx/service/config/RedisConfigService.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.sf.vertx.service.config;
-
-public interface RedisConfigService {
-
-}
diff --git a/sf-vertx/src/main/java/com/sf/vertx/service/impl/AppConfigServiceImpl.java b/sf-vertx/src/main/java/com/sf/vertx/service/impl/AppConfigServiceImpl.java
new file mode 100644
index 0000000..943ede9
--- /dev/null
+++ b/sf-vertx/src/main/java/com/sf/vertx/service/impl/AppConfigServiceImpl.java
@@ -0,0 +1,119 @@
+package com.sf.vertx.service.impl;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.sf.vertx.api.pojo.AppConfig;
+import com.sf.vertx.api.pojo.Node;
+import com.sf.vertx.api.pojo.VertxConfig;
+import com.sf.vertx.constans.RedisConfig;
+import com.sf.vertx.service.AppConfigService;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@Service
+public class AppConfigServiceImpl implements AppConfigService {
+ @Value("${server.vertx.environment}")
+ private String vertxEnvironment;
+ @Autowired
+ private RedisTemplate redisTemplate;
+
+ /***
+ * 从redis加载数据
+ */
+ public ConcurrentHashMap loadAllConfig() {
+ ConcurrentHashMap cacheAppConfig = new ConcurrentHashMap<>();
+ // 获取所有app列表
+ Set set = redisTemplate.opsForZSet().range(RedisConfig.APP_CONFIG_SET_KEY, 0, -1);
+ for(String appCode : set) {
+ String appCodeKey = RedisConfig.APP_CONFIG_PREFIX_KEY + ":" + appCode;
+ String appCodeValue = redisTemplate.opsForValue().get(appCodeKey);
+ if(StringUtils.isNotBlank(appCodeValue)) {
+ AppConfig appConfig = JSON.parseObject(appCodeValue, AppConfig.class);
+ cacheAppConfig.put(appCode, appConfig);
+
+ //JSONObject jsonObject = JSONObject.parseObject(appCodeValue);//从请求体里获得jsonObject
+ //String oldGoodsStorageModes = jsonObject.getString("nodeList");//解析成字符串
+ //字符串转list
+ //List oldGoodsStoragemodes = JSON.parseArray(oldGoodsStorageModes,Node.class);
+ //log.info("oldGoodsStoragemodes:{}", JSON.toJSONString(oldGoodsStoragemodes));
+ }
+ }
+ log.info("cacheAppConfig:{}", JSON.toJSONString(cacheAppConfig));
+ return cacheAppConfig;
+ }
+
+ public AppConfig getAppConfig(String appCode) {
+ String appCodeKey = RedisConfig.APP_CONFIG_PREFIX_KEY + ":" + appCode;
+ String appCodeValue = redisTemplate.opsForValue().get(appCodeKey);
+ if(StringUtils.isNotBlank(appCodeValue)) {
+ AppConfig appConfig = JSONObject.parseObject(appCodeValue, AppConfig.class);
+ return appConfig;
+ }
+ return null;
+ }
+
+ /***
+ * 新增、修改
+ * @param appConfig
+ */
+ public void addAppConfig(AppConfig appConfig) {
+ redisTemplate.opsForZSet().add(RedisConfig.APP_CONFIG_SET_KEY, appConfig.getAppCode(), 0);
+ String appCodeKey = RedisConfig.APP_CONFIG_PREFIX_KEY + ":" + appConfig.getAppCode();
+ redisTemplate.opsForValue().set(appCodeKey, JSONObject.toJSONString(appConfig));
+
+ // 发送redis队列,vertx处理
+ //String queue = RedisConfig.VETX_ENVIRONMENT_KEY+vertxEnvironment+":list";
+
+ }
+
+ /***
+ * 删除
+ * @param appConfig
+ */
+ public void deleteAppConfig(AppConfig appConfig) {
+ redisTemplate.opsForZSet().remove(RedisConfig.APP_CONFIG_SET_KEY, appConfig.getAppCode());
+ String appCodeKey = RedisConfig.APP_CONFIG_PREFIX_KEY + ":" + appConfig.getAppCode();
+ redisTemplate.delete(appCodeKey);
+
+
+ // 发送redis队列,vertx处理
+ //String queue = RedisConfig.VETX_ENVIRONMENT_KEY+vertxEnvironment+":list";
+ }
+
+
+ /***
+ * 加载vertx配置
+ */
+ public VertxConfig loadVertxConfig() {
+ String vertxConfigKey = RedisConfig.VERTX_CONFIG_STRING_KEY;
+ String vertxConfigValue = redisTemplate.opsForValue().get(vertxConfigKey);
+ if(StringUtils.isNotBlank(vertxConfigValue)) {
+ VertxConfig vertxConfig = JSONObject.parseObject(vertxConfigValue, VertxConfig.class);
+ return vertxConfig;
+ }
+ return null;
+ }
+
+ /***
+ * 新增、修改
+ * @param appConfig
+ */
+ public void addVertxConfig(VertxConfig vertxConfig) {
+ String vertxConfigKey = RedisConfig.VERTX_CONFIG_STRING_KEY;
+ redisTemplate.opsForValue().set(vertxConfigKey, JSONObject.toJSONString(vertxConfig));
+
+ // 发送redis队列,vertx处理
+ //String queue = RedisConfig.VETX_ENVIRONMENT_KEY+vertxEnvironment+":list";
+ }
+}
diff --git a/sf-vertx/src/main/java/com/sf/vertx/strategy/security/AesUtils.java b/sf-vertx/src/main/java/com/sf/vertx/strategy/security/AesUtils.java
new file mode 100644
index 0000000..691524b
--- /dev/null
+++ b/sf-vertx/src/main/java/com/sf/vertx/strategy/security/AesUtils.java
@@ -0,0 +1,84 @@
+package com.sf.vertx.strategy.security;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * 本类采用对称加密 加密算法:{@link #PADDINIG_MODE}
+ * {@link #RESULT_TYPE} 密文结果:1=base64 2=hex
+ */
+public class AesUtils {
+ /**
+ * 整平方法
+ */
+ private static final int RESULT_TYPE = 2;
+
+ /**
+ * 加密方法
+ */
+ private static final String AES_ALGORITHM = "AES";
+
+ /**
+ * 填充方法
+ */
+ private static final String PADDINIG_MODE = "AES/CBC/PKCS5Padding";
+
+ /**
+ * 偏移量
+ */
+ private static final byte[] IV = "0000000000000000".getBytes();
+
+ public static String encrypt(String s, String k) throws Exception {
+ SecretKeySpec key = new SecretKeySpec(StringUtils.getBytes(k), AES_ALGORITHM);
+ byte[] data = encrypt(StringUtils.getBytes(s), key);
+ String result;
+ switch (RESULT_TYPE) {
+ case 1:
+ result = Base64Utils.encode(data);
+ break;
+ case 2:
+ result = HexUtils.bytes2Hex(data);
+ break;
+ default:
+ throw new Exception("Unsupport Result Type");
+ }
+ return result;
+ }
+
+ public static String decrypt(String s, String k) throws Exception {
+ SecretKeySpec key = new SecretKeySpec(StringUtils.getBytes(k), AES_ALGORITHM);
+ byte[] data;
+ switch (RESULT_TYPE) {
+ case 1:
+ data = Base64Utils.decode(s);
+ break;
+ case 2:
+ data = HexUtils.hex2Bytes(s);
+ break;
+ default:
+ throw new Exception("Unsupport Result Type");
+ }
+ return StringUtils.bytes2String(decrypt(data, key));
+ }
+
+ private static byte[] encrypt(byte[] data, SecretKeySpec keySpec) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
+ IvParameterSpec ivspec = new IvParameterSpec(IV);
+ Cipher cipher = Cipher.getInstance(PADDINIG_MODE);
+ cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivspec);
+ return cipher.doFinal(data);
+ }
+
+ private static byte[] decrypt(byte[] data, SecretKeySpec keySpec) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
+ IvParameterSpec ivspec = new IvParameterSpec(IV);
+ Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+ cipher.init(Cipher.DECRYPT_MODE, keySpec, ivspec);
+ return cipher.doFinal(data);
+ }
+}
diff --git a/sf-vertx/src/main/java/com/sf/vertx/strategy/security/Base64Utils.java b/sf-vertx/src/main/java/com/sf/vertx/strategy/security/Base64Utils.java
new file mode 100644
index 0000000..06c9ff1
--- /dev/null
+++ b/sf-vertx/src/main/java/com/sf/vertx/strategy/security/Base64Utils.java
@@ -0,0 +1,31 @@
+package com.sf.vertx.strategy.security;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Base64;
+
+/**
+ * 将Base64字符串和字节数组互转
+ */
+public class Base64Utils {
+
+ /**
+ * 将字节数组编码为base64字符串
+ *
+ * @param b 字节数组
+ * @return String 字符串
+ */
+ public static String encode(byte[] b) {
+ return Base64.getEncoder().encodeToString(b);
+ }
+
+ /**
+ * 将字符串转base64为字节数组
+ *
+ * @param s 字符串
+ * @return byte[] 字节数组
+ */
+ public static byte[] decode(String s) {
+ return Base64.getDecoder().decode(s);
+ }
+
+}
diff --git a/sf-vertx/src/main/java/com/sf/vertx/strategy/security/HexUtils.java b/sf-vertx/src/main/java/com/sf/vertx/strategy/security/HexUtils.java
new file mode 100644
index 0000000..c274b71
--- /dev/null
+++ b/sf-vertx/src/main/java/com/sf/vertx/strategy/security/HexUtils.java
@@ -0,0 +1,53 @@
+package com.sf.vertx.strategy.security;
+
+/**
+ * 将字节数组和HEX字符串进行互转
+ */
+public class HexUtils {
+ private static final char[] HEX = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+
+ /**
+ * 字节数组转字符串
+ *
+ * @param byteArr 字节数组
+ * @return 字符串
+ */
+ public static String bytes2Hex(byte[] byteArr) {
+ StringBuilder sb = new StringBuilder(byteArr.length);
+ for (byte b : byteArr) {
+ String sTemp = Integer.toHexString(255 & b);
+ if (sTemp.length() < 2) {
+ sb.append(0);
+ }
+ sb.append(sTemp.toUpperCase());
+ }
+ return sb.toString();
+ }
+
+ /**
+ * HEX字符串转字节数组
+ *
+ * @param str 字符串
+ * @return 字节数组
+ */
+ public static byte[] hex2Bytes(String str) {
+ if (str == null) {
+ return null;
+ } else {
+ char[] hex = str.toCharArray();
+ int length = hex.length / 2;
+ byte[] raw = new byte[length];
+
+ for (int i = 0; i < length; ++i) {
+ int high = Character.digit(hex[i * 2], 16);
+ int low = Character.digit(hex[i * 2 + 1], 16);
+ int value = high << 4 | low;
+ if (value > 127) {
+ value -= 256;
+ }
+ raw[i] = (byte) value;
+ }
+ return raw;
+ }
+ }
+}
diff --git a/sf-vertx/src/main/java/com/sf/vertx/strategy/security/MainSecurity.java b/sf-vertx/src/main/java/com/sf/vertx/strategy/security/MainSecurity.java
new file mode 100644
index 0000000..a58e1cb
--- /dev/null
+++ b/sf-vertx/src/main/java/com/sf/vertx/strategy/security/MainSecurity.java
@@ -0,0 +1,78 @@
+package com.sf.vertx.strategy.security;
+
+import java.util.logging.Logger;
+
+/**
+ * 本项目中真正对外提供服务的工具类
+ */
+public class MainSecurity {
+ private static final Logger LOGGER = Logger.getLogger(MainSecurity.class.getName());
+
+ /**
+ * 加密,当失败的时候,返回空字符串
+ *
+ * @param content
+ * @param pubKey
+ * @return
+ */
+ public static String rsaEncrypt(String content, String pubKey) {
+ try {
+ return RSA2Utils.encrypt(content, pubKey);
+ } catch (Exception e) {
+ LOGGER.info("RSA加密失败");
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ public static String rsaDecrypt(String content, String priKey) {
+ try {
+ return RSA2Utils.decrypt(content, priKey);
+ } catch (Exception e) {
+ LOGGER.info("RSA解密失败");
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ public static String aesEncrypt(String content, String key) {
+ try {
+ return AesUtils.encrypt(content, key);
+ } catch (Exception e) {
+ e.printStackTrace();
+ LOGGER.info("AES加密失败");
+ return null;
+ }
+ }
+
+ public static String aesDecrypt(String content, String key) {
+ try {
+ return AesUtils.decrypt(content, key);
+ } catch (Exception e) {
+ e.printStackTrace();
+ LOGGER.info("AES解密失败");
+ return null;
+ }
+ }
+
+ public static String sign(String content) {
+ try {
+ return MessageDigest.md5(content);
+ } catch (Exception e) {
+ e.printStackTrace();
+ LOGGER.info("MD5加密失败");
+ return null;
+ }
+ }
+
+ public static void main(String[] args) {
+ System.out.println(aesEncrypt("{\n"
+ + " \"errorCode\": \"test\",\n"
+ + " \"result\": 0,\n"
+ + " \"data\": {\n"
+ + " \"username\" : \"test\"\n"
+ + " }\n"
+ + "}", "dadddsdfadfadsfa33323223"));
+ System.out.println(aesDecrypt("59A69B6BBCF046C3CF9953C5CC078CC68ABBED261030F3C119F65B9A3EB306423F32560751B22616500070BCE57153BE2B6E47CAC380C7D226862558256325826FECC43E957FCACB74E22BA48125FABC01FC77B127E384F8F62D9881741931A8C1ABF0A391F06606A060499EB53EF217", "dadddsdfadfadsfa33323223"));
+ }
+}
diff --git a/sf-vertx/src/main/java/com/sf/vertx/strategy/security/MessageDigest.java b/sf-vertx/src/main/java/com/sf/vertx/strategy/security/MessageDigest.java
new file mode 100644
index 0000000..b91b43b
--- /dev/null
+++ b/sf-vertx/src/main/java/com/sf/vertx/strategy/security/MessageDigest.java
@@ -0,0 +1,47 @@
+package com.sf.vertx.strategy.security;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import java.security.NoSuchAlgorithmException;
+
+public class MessageDigest {
+
+ public static String md5(String text) throws NoSuchAlgorithmException {
+ java.security.MessageDigest digest = java.security.MessageDigest.getInstance("md5");
+ byte[] buffer = digest.digest(text.getBytes());
+ StringBuilder sb = new StringBuilder();
+ for (byte b : buffer) {
+ int a = b & 0xff;
+ String hex = Integer.toHexString(a);
+
+ if (hex.length() == 1) {
+ hex = 0 + hex;
+ }
+ sb.append(hex);
+ }
+ return sb.toString();
+ }
+
+ private static String hmacSha1(String data, String key, int type) throws Exception {
+ //根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称
+ SecretKeySpec signinKey = new SecretKeySpec(key.getBytes(), "HmacSHA1");
+ //生成一个指定 Mac 算法 的 Mac 对象
+ Mac mac = Mac.getInstance("HmacSHA1");
+ //用给定密钥初始化 Mac 对象
+ mac.init(signinKey);
+ //完成 Mac 操作
+ byte[] rawHmac = mac.doFinal(StringUtils.getBytes(data));
+ String result;
+ switch (type) {
+ case 1:
+ result = Base64Utils.encode(rawHmac);
+ break;
+ case 2:
+ result = HexUtils.bytes2Hex(rawHmac);
+ break;
+ default:
+ throw new Exception("Unsupport Type");
+ }
+ return result;
+ }
+}
\ No newline at end of file
diff --git a/sf-vertx/src/main/java/com/sf/vertx/strategy/security/RSA2Utils.java b/sf-vertx/src/main/java/com/sf/vertx/strategy/security/RSA2Utils.java
new file mode 100644
index 0000000..70db5b2
--- /dev/null
+++ b/sf-vertx/src/main/java/com/sf/vertx/strategy/security/RSA2Utils.java
@@ -0,0 +1,282 @@
+package com.sf.vertx.strategy.security;
+
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.*;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 本类进行非对称加密,不推荐使用非对称加密对长字符串进行加密或者解密,徒增资源消耗,另外由于长度限制,过长的字符串的加密和解密会使用循环,对数据分段加密;本类采用的
+ * 密钥字符串均为Base64加密后的
+ * 另外所有异常都会抛出
+ * 下面将会列举几个可以自定义或者暴露出去的接口和参数
+ * {@link #IS_LONG_TEXT} 是否否对长文本处理
+ * {@link #RESULT_TYPE} 密文结果:1=base64 2=hex
+ * {@link #RSA_ALGORITHM} RSA算法
+ * {@link #encrypt(String, String)} 加密方法
+ * {@link #decrypt(String, String)} 解密方法
+ * {@link #getKeyPair} 解密方法
+ */
+public class RSA2Utils {
+ /**
+ * 是否对长文本加密;请参照{@link #MAX_DECRYPT_BLOCK}和{@link #MAX_ENCRYPT_BLOCK}
+ */
+ private static final boolean IS_LONG_TEXT = true;
+ /**
+ * 结果类型
+ */
+ private static final int RESULT_TYPE = 2;
+ /**
+ * RSA 算法
+ */
+ private static final String RSA_ALGORITHM = "RSA";
+ /**
+ * 长文本解密块大小
+ */
+ private static final int MAX_DECRYPT_BLOCK = 128;
+ /**
+ * 长文本加密块大小
+ */
+ private static final int MAX_ENCRYPT_BLOCK = 117;
+ /**
+ * KyeSize
+ */
+ private static final int KEY_SIZE = 2048;
+
+ /**
+ * 加密
+ *
+ * @param content 待加密的字符串
+ * @param pubKey 公钥字符串
+ * @return 加密后的文本
+ * @throws Exception 异常
+ */
+ public static String encrypt(String content, String pubKey) throws Exception {
+ byte[] data = StringUtils.getBytes(content);
+ PublicKey publicKey = string2PubKey(pubKey);
+ byte[] resultArr;
+ if (IS_LONG_TEXT) {
+ resultArr = encryptLongStr(data, publicKey);
+ } else {
+ resultArr = encrypt(data, publicKey);
+ }
+ String result;
+ switch (RESULT_TYPE) {
+ case 1:
+ result = Base64Utils.encode(resultArr);
+ break;
+ case 2:
+ result = HexUtils.bytes2Hex(resultArr);
+ break;
+ default:
+ throw new Exception("Unsupport result type");
+ }
+ return result;
+ }
+
+ /**
+ * @param content 密文内容
+ * @param priKey 私钥
+ * @return 解密后的字符串
+ * @throws Exception 异常
+ */
+ public static String decrypt(String content, String priKey) throws Exception {
+ byte[] data;
+ switch (RESULT_TYPE) {
+ case 1:
+ data = Base64Utils.decode(content);
+ break;
+ case 2:
+ data = HexUtils.hex2Bytes(content);
+ break;
+ default:
+ throw new Exception("Unsupport result type");
+ }
+ PrivateKey privateKey = string2PrivateKey(priKey);
+ byte[] result;
+ if (IS_LONG_TEXT) {
+ result = decryptLongStr(data, privateKey);
+ } else {
+ result = decrypt(privateKey, data);
+ }
+ return StringUtils.bytes2String(result);
+ }
+
+ /**
+ * 响应公私钥对
+ *
+ * @return 0号 公钥 1号 私钥
+ * @throws NoSuchAlgorithmException 异常
+ */
+ public static List getKeyPair() throws NoSuchAlgorithmException {
+ KeyPair keyPairObj = getKeyPairObj();
+ List data = new ArrayList<>();
+ data.add(Base64Utils.encode(keyPairObj.getPublic().getEncoded()));
+ data.add(Base64Utils.encode(keyPairObj.getPrivate().getEncoded()));
+ return data;
+ // jdk 17
+ //return List.of(Base64Utils.encode(keyPairObj.getPublic().getEncoded()), Base64Utils.encode(keyPairObj.getPrivate().getEncoded()));
+ }
+
+ /**
+ * 将公钥字符串转化为对象
+ *
+ * @param s base64字符串
+ * @return 公钥
+ * @throws NoSuchAlgorithmException 异常
+ * @throws UnsupportedEncodingException 异常
+ * @throws InvalidKeySpecException 异常
+ */
+ private static PublicKey string2PubKey(String s) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeySpecException {
+ KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
+ X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64Utils.decode(s));
+ return keyFactory.generatePublic(keySpec);
+ }
+
+ /**
+ * 对段字符串进行加密
+ *
+ * @param bytes 字节数组
+ * @param publicKey 公钥
+ * @return 加密后的数组
+ * @throws InvalidKeyException 异常
+ * @throws BadPaddingException 异常
+ * @throws IllegalBlockSizeException 异常
+ * @throws NoSuchPaddingException 异常
+ * @throws NoSuchAlgorithmException 异常
+ */
+ private static byte[] encrypt(byte[] bytes, PublicKey publicKey) throws InvalidKeyException, BadPaddingException, IllegalBlockSizeException, NoSuchPaddingException, NoSuchAlgorithmException {
+ Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
+ cipher.init(Cipher.ENCRYPT_MODE, publicKey);
+ return cipher.doFinal(bytes);
+ }
+
+ /**
+ * 对长字符串进行加密
+ *
+ * @param bytes 字节数组
+ * @param publicKey 公钥
+ * @return 加密后的数组
+ * @throws NoSuchPaddingException 异常
+ * @throws NoSuchAlgorithmException 异常
+ * @throws InvalidKeyException 异常
+ */
+ private static byte[] encryptLongStr(byte[] bytes, PublicKey publicKey) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException {
+ Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
+ cipher.init(Cipher.ENCRYPT_MODE, publicKey);
+ int inputLen = bytes.length;
+ byte[] encryptedData = new byte[0];
+ try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
+ int offSet = 0;
+ byte[] cache;
+ int i = 0;
+ // 对数据分段加密
+ while (inputLen - offSet > 0) {
+ if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
+ cache = cipher.doFinal(bytes, offSet, MAX_ENCRYPT_BLOCK);
+ } else {
+ cache = cipher.doFinal(bytes, offSet, inputLen - offSet);
+ }
+ out.write(cache, 0, cache.length);
+ i++;
+ offSet = i * MAX_ENCRYPT_BLOCK;
+ }
+ encryptedData = out.toByteArray();
+ } catch (IOException | BadPaddingException | IllegalBlockSizeException e) {
+ e.printStackTrace();
+ }
+ return encryptedData;
+ }
+
+ /**
+ * 私钥字符串转为私钥对象
+ *
+ * @param priStr 私钥字符串
+ * @return 私钥对象
+ * @throws NoSuchAlgorithmException 异常
+ * @throws InvalidKeySpecException 异常
+ */
+ private static PrivateKey string2PrivateKey(String priStr) throws NoSuchAlgorithmException, InvalidKeySpecException {
+ PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64Utils.decode(priStr));
+ KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
+ return keyFactory.generatePrivate(keySpec);
+ }
+
+ /**
+ * 解密
+ *
+ * @param privateKey 私钥
+ * @param bytes 字节数组
+ * @return 解密后的字节数组
+ * @throws NoSuchPaddingException 异常
+ * @throws NoSuchAlgorithmException 异常
+ * @throws BadPaddingException 异常
+ * @throws IllegalBlockSizeException 异常
+ * @throws InvalidKeyException 异常
+ */
+ public static byte[] decrypt(PrivateKey privateKey, byte[] bytes) throws NoSuchPaddingException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException {
+ Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
+ cipher.init(Cipher.DECRYPT_MODE, privateKey);
+ return cipher.doFinal(bytes);
+ }
+
+ /**
+ * 解密
+ *
+ * @param data 解密前的字节数组
+ * @param privateKey 私钥
+ * @return 解密后的字节数组
+ * @throws InvalidKeyException 异常
+ * @throws NoSuchPaddingException 异常
+ * @throws NoSuchAlgorithmException 异常
+ */
+ public static byte[] decryptLongStr(byte[] data, PrivateKey privateKey) throws InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException {
+ Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
+ cipher.init(Cipher.DECRYPT_MODE, privateKey);
+ int inputLen = data.length;
+ byte[] result = new byte[0];
+ try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
+ int offSet = 0;
+ byte[] cache;
+ int i = 0;
+ // 对数据分段解密
+ while (inputLen - offSet > 0) {
+ if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
+ cache = cipher.doFinal(data, offSet, MAX_DECRYPT_BLOCK);
+ } else {
+ cache = cipher.doFinal(data, offSet, inputLen - offSet);
+ }
+ out.write(cache, 0, cache.length);
+ i++;
+ offSet = i * MAX_DECRYPT_BLOCK;
+ }
+ result = out.toByteArray();
+ } catch (BadPaddingException | IllegalBlockSizeException | IOException e) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+
+ /**
+ * 获得一堆公私钥
+ *
+ * @return KeyPair对象
+ * @throws NoSuchAlgorithmException 异常
+ */
+ private static KeyPair getKeyPairObj() throws NoSuchAlgorithmException {
+ KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA_ALGORITHM);
+ SecureRandom secureRandom = new SecureRandom(StringUtils.getBytes(String.valueOf(System.currentTimeMillis())));
+ keyPairGenerator.initialize(KEY_SIZE, secureRandom);
+ return keyPairGenerator.genKeyPair();
+ }
+}
diff --git a/sf-vertx/src/main/java/com/sf/vertx/strategy/security/StringUtils.java b/sf-vertx/src/main/java/com/sf/vertx/strategy/security/StringUtils.java
new file mode 100644
index 0000000..c36668f
--- /dev/null
+++ b/sf-vertx/src/main/java/com/sf/vertx/strategy/security/StringUtils.java
@@ -0,0 +1,53 @@
+package com.sf.vertx.strategy.security;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+
+public class StringUtils {
+ /**
+ * 编码方法
+ */
+ private static final Charset CHARSET = StandardCharsets.UTF_8;
+
+ /**
+ * 根据本类的常量对字符串进行获取字节数组的操作
+ *
+ * @param s String:待处理的字符串
+ * @return byte[] 形成的字节数组
+ */
+ public static byte[] getBytes(String s) {
+ return s.getBytes(CHARSET);
+ }
+
+ /**
+ * 将字节数组转为文本
+ *
+ * @param data 字节数组
+ * @return 文本
+ */
+ public static String bytes2String(byte[] data) {
+ return new String(data, CHARSET);
+ }
+
+
+ /**
+ * 字符串是不是空的
+ *
+ * @param str 字符串
+ * @return 结果
+ */
+ public static boolean isBlank(String str) {
+ int strLen;
+ if (str != null && (strLen = str.length()) != 0) {
+ for (int i = 0; i < strLen; ++i) {
+ if (!Character.isWhitespace(str.charAt(i))) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ return true;
+ }
+ }
+
+}
diff --git a/sf-vertx/src/main/resources/application.yml b/sf-vertx/src/main/resources/application.yml
index 1c69b92..b03def3 100644
--- a/sf-vertx/src/main/resources/application.yml
+++ b/sf-vertx/src/main/resources/application.yml
@@ -2,6 +2,9 @@
server:
vertx:
environment: dev
+ server:
+ default:
+ port: 9099
# 服务器的HTTP端口,默认为8080
port: 5566
servlet:
diff --git a/sf-vertx/src/test/java/com/sf/vertx/TestEventBus.java b/sf-vertx/src/test/java/com/sf/vertx/TestEventBus.java
new file mode 100644
index 0000000..ef48008
--- /dev/null
+++ b/sf-vertx/src/test/java/com/sf/vertx/TestEventBus.java
@@ -0,0 +1,146 @@
+package com.sf.vertx;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import io.vertx.core.Vertx;
+import io.vertx.core.VertxOptions;
+import io.vertx.core.eventbus.EventBus;
+import io.vertx.core.eventbus.EventBusOptions;
+import io.vertx.core.eventbus.MessageConsumer;
+import io.vertx.ext.unit.Async;
+import io.vertx.ext.unit.TestContext;
+import io.vertx.ext.unit.junit.VertxUnitRunner;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@RunWith(VertxUnitRunner.class)
+public class TestEventBus {
+ private Vertx vertx;
+
+ @Before
+ public void setUp(TestContext tc) {
+ // 创建vertx服务
+ vertx = Vertx.vertx(new VertxOptions().setWorkerPoolSize(100));
+ }
+
+ @After
+ public void tearDown() {
+ vertx.close();
+ }
+
+ /***
+ * 发布订阅
+ *
+ * @param tc
+ */
+ @Test
+ public void testPublish(TestContext tc) {
+ Async async = tc.async();
+ EventBus eventBus = vertx.eventBus();
+ MessageConsumer consumer = eventBus.consumer("synAppCode");
+ consumer.handler(message -> {
+ System.out.println("consumer I have received a message: " + message.body());
+ message.reply("how interesting!");
+ });
+ consumer.completionHandler(res -> {
+ if (res.succeeded()) {
+ System.out.println("The handler registration has reached all nodes");
+ } else {
+ System.out.println("Registration failed!");
+ }
+ });
+
+ MessageConsumer consumer1 = eventBus.consumer("synAppCode");
+ consumer1.handler(message -> {
+ System.out.println("consumer1 I have received a message: " + message.body());
+ message.reply("how interesting!");
+ });
+ eventBus.publish("synAppCode", "hello world");
+ // eventBus.publish("synAppCode", "hello world");
+
+ eventBus.request("synAppCode", "Yay! Someone kicked a ball across a patch of grass", ar -> {
+ if (ar.succeeded()) {
+ System.out.println("Received reply: " + ar.result().body());
+ }
+ });
+ }
+
+ /***
+ * 点点发送 在对应地址上注册过的所有处理器中, 仅一个处理器能够接收到发送的消息。 这是一种点对点消息传递模式。 Vert.x
+ * 使用不严格的轮询算法来选择绑定的处理器。
+ *
+ * @param tc
+ */
+ @Test
+ public void testSend(TestContext tc) {
+ Async async = tc.async();
+ EventBus eb = vertx.eventBus();
+ MessageConsumer consumer = eb.consumer("synAppCode");
+ consumer.handler(message -> {
+ System.out.println("consumer I have received a message: " + message.body());
+ });
+ consumer.completionHandler(res -> {
+ if (res.succeeded()) {
+ System.out.println("The handler registration has reached all nodes");
+ } else {
+ System.out.println("Registration failed!");
+ }
+ });
+
+ MessageConsumer consumer1 = eb.consumer("synAppCode");
+ consumer1.handler(message -> {
+ System.out.println("consumer1 I have received a message: " + message.body());
+ });
+ eb.send("synAppCode", "hello world");
+ }
+
+ @Test
+ public void clusterConsumer(TestContext tc) {
+ Async async = tc.async();
+ VertxOptions options = new VertxOptions()
+ .setEventBusOptions(new EventBusOptions().setClusterPublicHost("192.168.1.68").setClusterPublicPort(1));
+
+ Vertx.clusteredVertx(options).onComplete(res -> {
+ if (res.succeeded()) {
+ Vertx vertx = res.result();
+ EventBus eventBus = vertx.eventBus();
+ MessageConsumer consumer = eventBus.consumer("synAppCode");
+ consumer.handler(message -> {
+ System.out.println("consumer I have received a message: " + message.body());
+ });
+ consumer.completionHandler(resData -> {
+ if (res.succeeded()) {
+ System.out.println("The handler registration has reached all nodes");
+ } else {
+ System.out.println("Registration failed!");
+ }
+ });
+ eventBus.publish("synAppCode", "hello world");
+ System.out.println("We now have a clustered event bus: " + eventBus);
+ } else {
+ System.out.println("Failed: " + res.cause());
+ }
+ });
+ }
+
+ @Test
+ public void clusterPublish(TestContext tc) {
+ Async async = tc.async();
+ VertxOptions options = new VertxOptions()
+ .setEventBusOptions(new EventBusOptions().setClusterPublicHost("192.168.1.68").setClusterPublicPort(2));
+
+ Vertx.clusteredVertx(options).onComplete(res -> {
+ if (res.succeeded()) {
+ Vertx vertx = res.result();
+ EventBus eventBus = vertx.eventBus();
+ eventBus.publish("synAppCode", "hello world");
+ } else {
+ System.out.println("Failed: " + res.cause());
+ }
+ });
+ }
+
+}
diff --git a/sf-vertx/src/test/java/com/sf/vertx/TestJson.java b/sf-vertx/src/test/java/com/sf/vertx/TestJson.java
new file mode 100644
index 0000000..9a0cecd
--- /dev/null
+++ b/sf-vertx/src/test/java/com/sf/vertx/TestJson.java
@@ -0,0 +1,35 @@
+package com.sf.vertx;
+
+import java.util.List;
+
+import org.junit.Test;
+
+import com.alibaba.fastjson2.JSON;
+import com.sf.vertx.api.pojo.Node;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class TestJson {
+
+ @Test
+ public void json() {
+ String oldGoodsStorageModes = " [\n"
+ + " {\n"
+ + " \"createHttp\": true,\n"
+ + " \"createHttps\": false,\n"
+ + " \"ip\": \"localhost\",\n"
+ + " \"port\": \"9198\"\n"
+ + " },\n"
+ + " {\n"
+ + " \"createHttp\": true,\n"
+ + " \"createHttps\": false,\n"
+ + " \"ip\": \"localhost\",\n"
+ + " \"port\": \"9199\"\n"
+ + " }\n"
+ + " ]";//解析成字符串
+ //字符串转list
+ List oldGoodsStoragemodes = JSON.parseArray(oldGoodsStorageModes,Node.class);
+ log.info("oldGoodsStoragemodes:{}", JSON.toJSONString(oldGoodsStoragemodes));
+ }
+}
diff --git a/sf-vertx/src/test/java/com/sf/vertx/TestProxy.java b/sf-vertx/src/test/java/com/sf/vertx/TestProxy.java
index c1220b1..410c6c8 100644
--- a/sf-vertx/src/test/java/com/sf/vertx/TestProxy.java
+++ b/sf-vertx/src/test/java/com/sf/vertx/TestProxy.java
@@ -14,6 +14,8 @@ 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.eventbus.EventBus;
+import io.vertx.core.eventbus.MessageConsumer;
import io.vertx.core.http.HttpClient;
import io.vertx.core.http.HttpClientOptions;
import io.vertx.core.http.HttpServer;
@@ -39,6 +41,16 @@ public class TestProxy {
routeUrilRewrite();
}
+ public static void eventBus() {
+ // 创建vertx服务
+ Vertx VERTX = Vertx.vertx(new VertxOptions().setWorkerPoolSize(100));
+ EventBus eb = VERTX.eventBus();
+ MessageConsumer consumer = eb.consumer("news.uk.sport");
+ consumer.handler(message -> {
+ System.out.println("I have received a message: " + message.body());
+ });
+ }
+
/***
* 测试url重写, 入口/appCode/xxxx/xxx, 转换为/xxxx/xxx
*/
@@ -57,6 +69,8 @@ public class TestProxy {
}
});
+
+
HttpClientOptions clientOptions = new HttpClientOptions();
clientOptions.setMaxPoolSize(20); // 最大连接池大小
clientOptions.setConnectTimeout(5000); // 连接超时 毫秒
@@ -64,16 +78,16 @@ public class TestProxy {
clientOptions.setIdleTimeout(1000); // 连接空闲超时 毫秒
HttpClient proxyClient = VERTX.createHttpClient(clientOptions);
HttpProxy proxy = HttpProxy.reverseProxy(proxyClient);
-
+
proxy.originSelector(request -> Future.succeededFuture(resolveOriginAddress(request)));
SFProxyHandler sfProxyHandler = SFProxyHandler.create(proxy);
WebClient mainWebClient = WebClient.create(VERTX);
proxy.addInterceptor(new ProxyInterceptor() {
@Override
public Future handleProxyRequest(ProxyContext context) {
- SFProxyHandlerImpl sfProxyHandlerImpl = (SFProxyHandlerImpl)sfProxyHandler;
- //String body = sfProxyHandlerImpl.getCtx().getBodyAsString();
- //log.info("ctx.getBodyAsJson():{}", body);
+ SFProxyHandlerImpl sfProxyHandlerImpl = (SFProxyHandlerImpl) sfProxyHandler;
+ // String body = sfProxyHandlerImpl.getCtx().getBodyAsString();
+ // log.info("ctx.getBodyAsJson():{}", body);
JsonObject bodyJson = sfProxyHandlerImpl.getCtx().getBodyAsJson();
HttpServerRequest HttpServerRequest = context.request().proxiedRequest();
// 解密
@@ -81,7 +95,7 @@ public class TestProxy {
bodyJson.put("data", data);
// end解密
// uri重写
- //context.request().setURI("/vertx/body");
+ // context.request().setURI("/vertx/body");
return Future.future(p -> {
mainWebClient.postAbs("http://localhost:9198/vertx/body").sendJson(bodyJson.toString(), h -> {
if (h.succeeded()) {
@@ -91,8 +105,9 @@ public class TestProxy {
JsonObject responseData = h.result().bodyAsJsonObject();
// responseData.toBuffer()
// 加密
- String dataStr = MainSecurity.aesEncrypt(responseData.toString(), "dadddsdfadfadsfa33323223");
- log.info("dataStr:{}",dataStr);
+ String dataStr = MainSecurity.aesEncrypt(responseData.toString(),
+ "dadddsdfadfadsfa33323223");
+ log.info("dataStr:{}", dataStr);
Buffer buffer = Buffer.buffer(dataStr);
// end 加密
ProxyResponse proxyResponse = proxyRequest.response().setStatusCode(200)
@@ -105,7 +120,7 @@ public class TestProxy {
});
}
});
- //mainHttpRouter.route().handler(sfProxyHandler);
+ // mainHttpRouter.route().handler(sfProxyHandler);
mainHttpRouter.route().handler(BodyHandler.create()).handler(sfProxyHandler);
}
diff --git a/sf-vertx/src/test/java/com/sf/vertx/TestZookeeper.java b/sf-vertx/src/test/java/com/sf/vertx/TestZookeeper.java
new file mode 100644
index 0000000..91231ca
--- /dev/null
+++ b/sf-vertx/src/test/java/com/sf/vertx/TestZookeeper.java
@@ -0,0 +1,40 @@
+//package com.sf.vertx;
+//
+//import org.junit.Test;
+//import org.junit.runner.RunWith;
+//
+//import io.vertx.core.Vertx;
+//import io.vertx.core.VertxOptions;
+//import io.vertx.core.json.JsonObject;
+//import io.vertx.core.spi.cluster.ClusterManager;
+//import io.vertx.ext.unit.Async;
+//import io.vertx.ext.unit.TestContext;
+//import io.vertx.ext.unit.junit.VertxUnitRunner;
+//import io.vertx.spi.cluster.zookeeper.ZookeeperClusterManager;
+//import lombok.extern.slf4j.Slf4j;
+//
+//@Slf4j
+//@RunWith(VertxUnitRunner.class)
+//public class TestZookeeper {
+//
+// @Test
+// public void clusterZookeepre(TestContext tc) {
+// Async async = tc.async();
+// JsonObject zkConfig = new JsonObject();
+// zkConfig.put("zookeeperHosts", "127.0.0.1");
+// zkConfig.put("rootPath", "io.vertx");
+// zkConfig.put("retry", new JsonObject().put("initialSleepTime", 3000).put("maxTimes", 3));
+//
+// ClusterManager mgr = new ZookeeperClusterManager(zkConfig);
+// VertxOptions options = new VertxOptions().setClusterManager(mgr);
+//
+// Vertx.clusteredVertx(options, res -> {
+// if (res.succeeded()) {
+// Vertx vertx = res.result();
+// log.info("success");
+// } else {
+// log.info("error:{}",res.cause());
+// }
+// });
+// }
+//}
diff --git a/sf-vertx/src/test/resources/zookeeper.json b/sf-vertx/src/test/resources/zookeeper.json
new file mode 100644
index 0000000..e69de29