vertx 网关实现:
1、配置动态生成代理 2、负载均衡算法 轮训 3、加解密
This commit is contained in:
parent
fd552c9732
commit
86240708eb
5
pom.xml
5
pom.xml
@ -172,6 +172,11 @@
|
|||||||
<artifactId>sf-apijson</artifactId>
|
<artifactId>sf-apijson</artifactId>
|
||||||
<version>${sf.version}</version>
|
<version>${sf.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.smarterFramework</groupId>
|
||||||
|
<artifactId>sf-vertx-api</artifactId>
|
||||||
|
<version>${sf.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-core</artifactId>
|
<artifactId>hutool-core</artifactId>
|
||||||
|
@ -1,26 +1,28 @@
|
|||||||
package com.sf.deployment.controller;
|
package com.sf.system.deployment.controller;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
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.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.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.PutMapping;
|
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.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import com.sf.common.annotation.Log;
|
import com.sf.common.annotation.Log;
|
||||||
import com.sf.common.core.controller.BaseController;
|
import com.sf.common.core.controller.BaseController;
|
||||||
import com.sf.common.core.domain.AjaxResult;
|
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.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
|
* 环境维护Controller
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package com.sf.deployment.mapper;
|
package com.sf.system.deployment.mapper;
|
||||||
|
|
||||||
import com.sf.system.deployment.domain.DeploymentApplyEnvironment;
|
import com.sf.system.deployment.domain.DeploymentApplyEnvironment;
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package com.sf.deployment.service;
|
package com.sf.system.deployment.service;
|
||||||
|
|
||||||
import com.sf.system.deployment.domain.DeploymentApplyEnvironment;
|
import com.sf.system.deployment.domain.DeploymentApplyEnvironment;
|
||||||
|
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
package com.sf.deployment.service.impl;
|
package com.sf.system.deployment.service.impl;
|
||||||
|
|
||||||
import java.util.List;
|
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.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
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业务层处理
|
* 环境维护Service业务层处理
|
||||||
|
@ -19,21 +19,23 @@
|
|||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- 阿里JSON解析器 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.fastjson2</groupId>
|
||||||
|
<artifactId>fastjson2</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-war-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>3.1.0</version>
|
|
||||||
<configuration>
|
<configuration>
|
||||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
<source>1.8</source>
|
||||||
<warName>${project.artifactId}</warName>
|
<target>1.8</target>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
<finalName>${project.artifactId}</finalName>
|
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
</project>
|
</project>
|
@ -8,7 +8,8 @@ import lombok.Data;
|
|||||||
@Data
|
@Data
|
||||||
public class AppConfig implements Serializable {
|
public class AppConfig implements Serializable {
|
||||||
private static final long serialVersionUID = 1518165296680157119L;
|
private static final long serialVersionUID = 1518165296680157119L;
|
||||||
|
private String appCode;
|
||||||
private boolean exclusiveService; // 预留字段, 独立端口
|
private boolean exclusiveService; // 预留字段, 独立端口
|
||||||
private List<ServerAddress> serverAddressList;
|
private List<Node> nodeList;
|
||||||
|
private List<Strategy> strategyList;
|
||||||
}
|
}
|
||||||
|
@ -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; // 私钥
|
||||||
|
}
|
@ -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; // 大写
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
110
sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/Node.java
Normal file
110
sf-vertx-api/src/main/java/com/sf/vertx/api/pojo/Node.java
Normal file
@ -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 <br>
|
||||||
|
* final Integer weight:权重,保存配置的权重 <br>
|
||||||
|
* Integer effectiveWeight:有效权重,轮询的过程权重可能变化 <br>
|
||||||
|
* Integer currentWeight:当前权重,比对该值大小获取节点<br>
|
||||||
|
* 第一次加权轮询时:currentWeight = weight = effectiveWeight <br>
|
||||||
|
* 后面每次加权轮询时:currentWeight 的值都会不断变化,其他权重不变 <br>
|
||||||
|
*/
|
||||||
|
public class Node implements Comparable<Node>, 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 + "}";
|
||||||
|
}
|
||||||
|
}
|
@ -1,14 +1,14 @@
|
|||||||
package com.sf.vertx.api.pojo;
|
//package com.sf.vertx.api.pojo;
|
||||||
|
//
|
||||||
import java.io.Serializable;
|
//import java.io.Serializable;
|
||||||
|
//
|
||||||
import lombok.Data;
|
//import lombok.Data;
|
||||||
|
//
|
||||||
@Data
|
//@Data
|
||||||
public class ServerAddress implements Serializable {
|
//public class ServerAddress implements Serializable {
|
||||||
private static final long serialVersionUID = 2821255113510132943L;
|
// private static final long serialVersionUID = 2821255113510132943L;
|
||||||
private boolean createHttp; // 协议
|
// private boolean createHttp; // 协议
|
||||||
private boolean createHttps;
|
// private boolean createHttps;
|
||||||
private String ip;
|
// private String ip;
|
||||||
private int port;
|
// private int port;
|
||||||
}
|
//}
|
||||||
|
@ -1,14 +1,21 @@
|
|||||||
package com.sf.vertx.api.pojo;
|
package com.sf.vertx.api.pojo;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* 策略
|
* 策略
|
||||||
* @author xy
|
* @author xy
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@Data
|
||||||
public class Strategy implements Serializable {
|
public class Strategy implements Serializable {
|
||||||
private static final long serialVersionUID = -8831406773224882471L;
|
private static final long serialVersionUID = -8831406773224882471L;
|
||||||
|
private DataSecurity dataSecurity;
|
||||||
|
private List<GatewayInterface> gatewayInterfaceList;
|
||||||
|
private HttpClientOptionsConfig httpClientOptionsConfig; // 高并发情况,配置接口连接池
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.sf.vertx.arithmetic.roundRobin;
|
||||||
|
|
||||||
|
import com.sf.vertx.api.pojo.Node;
|
||||||
|
|
||||||
|
public interface SacLoadBalancing {
|
||||||
|
Node selectNode();
|
||||||
|
}
|
@ -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<Node> 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<Node> 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<Node> 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<Node> 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");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -30,6 +30,10 @@
|
|||||||
|
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.smarterFramework</groupId>
|
||||||
|
<artifactId>sf-vertx-api</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
@ -61,6 +65,22 @@
|
|||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-pool2</artifactId>
|
<artifactId>commons-pool2</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!--
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.vertx</groupId>
|
||||||
|
<artifactId>vertx-hazelcast</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.vertx</groupId>
|
||||||
|
<artifactId>vertx-zookeeper</artifactId>
|
||||||
|
</dependency>
|
||||||
|
-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.vertx</groupId>
|
||||||
|
<artifactId>vertx-unit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
<!-- Generators -->
|
<!-- Generators -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.vertx</groupId>
|
<groupId>io.vertx</groupId>
|
||||||
@ -115,11 +135,10 @@
|
|||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
<artifactId>jackson-databind</artifactId>
|
<artifactId>jackson-databind</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
|
<!-- 阿里JSON解析器 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba</groupId>
|
<groupId>com.alibaba.fastjson2</groupId>
|
||||||
<artifactId>fastjson</artifactId>
|
<artifactId>fastjson2</artifactId>
|
||||||
<version>2.0.48</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
@ -129,10 +148,10 @@
|
|||||||
<artifactId>slf4j-api</artifactId>
|
<artifactId>slf4j-api</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>slf4j-simple</artifactId>
|
<artifactId>slf4j-simple</artifactId>
|
||||||
<type>jar</type>
|
<type>jar</type>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ch.qos.logback</groupId>
|
<groupId>ch.qos.logback</groupId>
|
||||||
<artifactId>logback-classic</artifactId>
|
<artifactId>logback-classic</artifactId>
|
||||||
@ -147,6 +166,11 @@
|
|||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-lang3</artifactId>
|
<artifactId>commons-lang3</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.netty</groupId>
|
||||||
|
<artifactId>netty-all</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -26,6 +26,5 @@ public class AdminApplication {
|
|||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
// System.setProperty("spring.devtools.restart.enabled", "false");
|
// System.setProperty("spring.devtools.restart.enabled", "false");
|
||||||
APPLICATION_CONTEXT = SpringApplication.run(AdminApplication.class, args);
|
APPLICATION_CONTEXT = SpringApplication.run(AdminApplication.class, args);
|
||||||
log.info("dafafsdfa:{}", "dsafs");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,24 @@
|
|||||||
package com.sf.vertx.constans;
|
package com.sf.vertx.constans;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
|
||||||
|
@Component
|
||||||
public class RedisConfig {
|
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";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -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<String, String> 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<String> 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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,36 +1,33 @@
|
|||||||
package com.sf.vertx.init;
|
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.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.boot.ApplicationArguments;
|
import org.springframework.boot.ApplicationArguments;
|
||||||
import org.springframework.boot.ApplicationRunner;
|
import org.springframework.boot.ApplicationRunner;
|
||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
import com.sf.vertx.api.pojo.AppConfig;
|
||||||
import com.sf.vertx.security.MainSecurity;
|
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.Future;
|
||||||
import io.vertx.core.Vertx;
|
import io.vertx.core.Vertx;
|
||||||
import io.vertx.core.VertxOptions;
|
import io.vertx.core.VertxOptions;
|
||||||
import io.vertx.core.buffer.Buffer;
|
|
||||||
import io.vertx.core.http.HttpClient;
|
import io.vertx.core.http.HttpClient;
|
||||||
import io.vertx.core.http.HttpClientOptions;
|
|
||||||
import io.vertx.core.http.HttpServer;
|
import io.vertx.core.http.HttpServer;
|
||||||
import io.vertx.core.http.HttpServerRequest;
|
import io.vertx.core.http.HttpServerRequest;
|
||||||
import io.vertx.core.net.SocketAddress;
|
import io.vertx.core.net.SocketAddress;
|
||||||
import io.vertx.ext.web.Router;
|
import io.vertx.ext.web.Router;
|
||||||
import io.vertx.ext.web.handler.BodyHandler;
|
|
||||||
import io.vertx.ext.web.proxy.handler.ProxyHandler;
|
import io.vertx.ext.web.proxy.handler.ProxyHandler;
|
||||||
import io.vertx.httpproxy.Body;
|
|
||||||
import io.vertx.httpproxy.HttpProxy;
|
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;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
/***
|
/***
|
||||||
@ -43,31 +40,91 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
@Order(value = 10)
|
@Order(value = 10)
|
||||||
@Component
|
@Component
|
||||||
public class DynamicBuildServer implements ApplicationRunner {
|
public class DynamicBuildServer implements ApplicationRunner {
|
||||||
|
@Value("${server.vertx.server.default.port}")
|
||||||
|
private Integer serverDefaultPort;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private RedisTemplate<String, String> redisTemplate;
|
private AppConfigService appConfigService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RedisConfig redisConfig;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(ApplicationArguments args) throws Exception {
|
public void run(ApplicationArguments args) throws Exception {
|
||||||
|
// 初始化redis key
|
||||||
|
redisConfig.init();
|
||||||
|
|
||||||
|
// 加载vertx、应用配置
|
||||||
appStartLoadData();
|
appStartLoadData();
|
||||||
|
|
||||||
// 创建服务
|
|
||||||
|
|
||||||
// 创建路由
|
|
||||||
|
|
||||||
// 创建非加密路由
|
|
||||||
|
|
||||||
// 创建加密路由
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* 应用启动, 从redis读取配置,初始化vertx服务
|
* 应用启动, 从redis读取配置,初始化vertx服务
|
||||||
*/
|
*/
|
||||||
private void appStartLoadData() {
|
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<String, AppConfig> 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<Node> 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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<String, AppConfig> loadAllConfig();
|
||||||
|
|
||||||
|
void addAppConfig(AppConfig appConfig);
|
||||||
|
|
||||||
|
void deleteAppConfig(AppConfig appConfig);
|
||||||
|
|
||||||
|
VertxConfig loadVertxConfig();
|
||||||
|
|
||||||
|
void addVertxConfig(VertxConfig vertxConfig);
|
||||||
|
}
|
@ -1,5 +0,0 @@
|
|||||||
package com.sf.vertx.service.config;
|
|
||||||
|
|
||||||
public interface RedisConfigService {
|
|
||||||
|
|
||||||
}
|
|
@ -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<String, String> redisTemplate;
|
||||||
|
|
||||||
|
/***
|
||||||
|
* 从redis加载数据
|
||||||
|
*/
|
||||||
|
public ConcurrentHashMap<String, AppConfig> loadAllConfig() {
|
||||||
|
ConcurrentHashMap<String, AppConfig> cacheAppConfig = new ConcurrentHashMap<>();
|
||||||
|
// 获取所有app列表
|
||||||
|
Set<String> 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<Node> 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";
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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"));
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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<String> getKeyPair() throws NoSuchAlgorithmException {
|
||||||
|
KeyPair keyPairObj = getKeyPairObj();
|
||||||
|
List<String> 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();
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -2,6 +2,9 @@
|
|||||||
server:
|
server:
|
||||||
vertx:
|
vertx:
|
||||||
environment: dev
|
environment: dev
|
||||||
|
server:
|
||||||
|
default:
|
||||||
|
port: 9099
|
||||||
# 服务器的HTTP端口,默认为8080
|
# 服务器的HTTP端口,默认为8080
|
||||||
port: 5566
|
port: 5566
|
||||||
servlet:
|
servlet:
|
||||||
|
146
sf-vertx/src/test/java/com/sf/vertx/TestEventBus.java
Normal file
146
sf-vertx/src/test/java/com/sf/vertx/TestEventBus.java
Normal file
@ -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<String> 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<String> 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<String> 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<String> 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<String> 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());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
35
sf-vertx/src/test/java/com/sf/vertx/TestJson.java
Normal file
35
sf-vertx/src/test/java/com/sf/vertx/TestJson.java
Normal file
@ -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<Node> oldGoodsStoragemodes = JSON.parseArray(oldGoodsStorageModes,Node.class);
|
||||||
|
log.info("oldGoodsStoragemodes:{}", JSON.toJSONString(oldGoodsStoragemodes));
|
||||||
|
}
|
||||||
|
}
|
@ -14,6 +14,8 @@ import io.vertx.core.Future;
|
|||||||
import io.vertx.core.Vertx;
|
import io.vertx.core.Vertx;
|
||||||
import io.vertx.core.VertxOptions;
|
import io.vertx.core.VertxOptions;
|
||||||
import io.vertx.core.buffer.Buffer;
|
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.HttpClient;
|
||||||
import io.vertx.core.http.HttpClientOptions;
|
import io.vertx.core.http.HttpClientOptions;
|
||||||
import io.vertx.core.http.HttpServer;
|
import io.vertx.core.http.HttpServer;
|
||||||
@ -39,6 +41,16 @@ public class TestProxy {
|
|||||||
routeUrilRewrite();
|
routeUrilRewrite();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void eventBus() {
|
||||||
|
// 创建vertx服务
|
||||||
|
Vertx VERTX = Vertx.vertx(new VertxOptions().setWorkerPoolSize(100));
|
||||||
|
EventBus eb = VERTX.eventBus();
|
||||||
|
MessageConsumer<String> 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
|
* 测试url重写, 入口/appCode/xxxx/xxx, 转换为/xxxx/xxx
|
||||||
*/
|
*/
|
||||||
@ -57,6 +69,8 @@ public class TestProxy {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
HttpClientOptions clientOptions = new HttpClientOptions();
|
HttpClientOptions clientOptions = new HttpClientOptions();
|
||||||
clientOptions.setMaxPoolSize(20); // 最大连接池大小
|
clientOptions.setMaxPoolSize(20); // 最大连接池大小
|
||||||
clientOptions.setConnectTimeout(5000); // 连接超时 毫秒
|
clientOptions.setConnectTimeout(5000); // 连接超时 毫秒
|
||||||
@ -71,9 +85,9 @@ public class TestProxy {
|
|||||||
proxy.addInterceptor(new ProxyInterceptor() {
|
proxy.addInterceptor(new ProxyInterceptor() {
|
||||||
@Override
|
@Override
|
||||||
public Future<ProxyResponse> handleProxyRequest(ProxyContext context) {
|
public Future<ProxyResponse> handleProxyRequest(ProxyContext context) {
|
||||||
SFProxyHandlerImpl sfProxyHandlerImpl = (SFProxyHandlerImpl)sfProxyHandler;
|
SFProxyHandlerImpl sfProxyHandlerImpl = (SFProxyHandlerImpl) sfProxyHandler;
|
||||||
//String body = sfProxyHandlerImpl.getCtx().getBodyAsString();
|
// String body = sfProxyHandlerImpl.getCtx().getBodyAsString();
|
||||||
//log.info("ctx.getBodyAsJson():{}", body);
|
// log.info("ctx.getBodyAsJson():{}", body);
|
||||||
JsonObject bodyJson = sfProxyHandlerImpl.getCtx().getBodyAsJson();
|
JsonObject bodyJson = sfProxyHandlerImpl.getCtx().getBodyAsJson();
|
||||||
HttpServerRequest HttpServerRequest = context.request().proxiedRequest();
|
HttpServerRequest HttpServerRequest = context.request().proxiedRequest();
|
||||||
// 解密
|
// 解密
|
||||||
@ -81,7 +95,7 @@ public class TestProxy {
|
|||||||
bodyJson.put("data", data);
|
bodyJson.put("data", data);
|
||||||
// end解密
|
// end解密
|
||||||
// uri重写
|
// uri重写
|
||||||
//context.request().setURI("/vertx/body");
|
// context.request().setURI("/vertx/body");
|
||||||
return Future.future(p -> {
|
return Future.future(p -> {
|
||||||
mainWebClient.postAbs("http://localhost:9198/vertx/body").sendJson(bodyJson.toString(), h -> {
|
mainWebClient.postAbs("http://localhost:9198/vertx/body").sendJson(bodyJson.toString(), h -> {
|
||||||
if (h.succeeded()) {
|
if (h.succeeded()) {
|
||||||
@ -91,8 +105,9 @@ public class TestProxy {
|
|||||||
JsonObject responseData = h.result().bodyAsJsonObject();
|
JsonObject responseData = h.result().bodyAsJsonObject();
|
||||||
// responseData.toBuffer()
|
// responseData.toBuffer()
|
||||||
// 加密
|
// 加密
|
||||||
String dataStr = MainSecurity.aesEncrypt(responseData.toString(), "dadddsdfadfadsfa33323223");
|
String dataStr = MainSecurity.aesEncrypt(responseData.toString(),
|
||||||
log.info("dataStr:{}",dataStr);
|
"dadddsdfadfadsfa33323223");
|
||||||
|
log.info("dataStr:{}", dataStr);
|
||||||
Buffer buffer = Buffer.buffer(dataStr);
|
Buffer buffer = Buffer.buffer(dataStr);
|
||||||
// end 加密
|
// end 加密
|
||||||
ProxyResponse proxyResponse = proxyRequest.response().setStatusCode(200)
|
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);
|
mainHttpRouter.route().handler(BodyHandler.create()).handler(sfProxyHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
40
sf-vertx/src/test/java/com/sf/vertx/TestZookeeper.java
Normal file
40
sf-vertx/src/test/java/com/sf/vertx/TestZookeeper.java
Normal file
@ -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());
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
//}
|
0
sf-vertx/src/test/resources/zookeeper.json
Normal file
0
sf-vertx/src/test/resources/zookeeper.json
Normal file
Loading…
x
Reference in New Issue
Block a user