routeDefinitionList = serviceRouteInfo.getRouteDefinitionList();
+ for (GatewayRouteDefinition gatewayRouteDefinition : routeDefinitionList) {
+ T routeDefinition = this.buildRouteDefinition(serviceRouteInfo, gatewayRouteDefinition);
+ routeRepository.add(routeDefinition);
+ }
+ } catch (Exception e) {
+ log.error("加载路由信息失败,serviceRouteInfo:{}", serviceRouteInfo, e);
+ }
+ }
+
+ @Override
+ public void remove(String serviceId) {
+ serviceIdMd5Map.remove(serviceId);
+ routeRepository.deleteAll(serviceId);
+ }
+}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/BaseRouteManager.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/BaseRouteManager.java
deleted file mode 100644
index 4b4ea6ec..00000000
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/BaseRouteManager.java
+++ /dev/null
@@ -1,220 +0,0 @@
-package com.gitee.sop.gatewaycommon.manager;
-
-import com.alibaba.fastjson.JSON;
-import com.gitee.sop.gatewaycommon.bean.BaseRouteDefinition;
-import com.gitee.sop.gatewaycommon.bean.BaseServiceRouteInfo;
-import com.gitee.sop.gatewaycommon.bean.TargetRoute;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.curator.framework.recipes.cache.ChildData;
-import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
-import org.springframework.core.env.Environment;
-
-
-/**
- * 路由管理,采用zookeeper实现,监听路由的增删改,并适时更新到本地。路由的存储格式为:
- *
- * /com.gitee.sop.route 根节点
- * /serviceId 服务节点,名字为服务名
- * /route1 路由节点,名字为:name+version,存放路由信息
- * /route2
- * /...
- *
- *
- * @param 路由根对象,可以理解为最外面的大json:{....,routeDefinitionList:[]}
- * @param 路由Item对象,对应大json里面的具体路由信息,routeDefinitionList:[]
- * @param 目标路由对象
- * @author tanghc
- */
-@Slf4j
-public abstract class BaseRouteManager, E extends BaseRouteDefinition, T extends TargetRoute> implements RouteManager {
-
- protected Environment environment;
-
- protected RouteRepository routeRepository;
-
- protected String routeRootPath;
-
- /**
- * 返回路由根对象class
- *
- * @return 返回R.class
- */
- protected abstract Class getServiceRouteInfoClass();
-
- /**
- * 返回路由Item对象class
- *
- * @return 返回E.class
- */
- protected abstract Class getRouteDefinitionClass();
-
- /**
- * 构建目标路由对象,zuul和gateway定义的路由对象
- *
- * @param serviceRouteInfo
- * @param routeDefinition
- * @return 返回目标路由对象
- */
- protected abstract T buildRouteDefinition(R serviceRouteInfo, E routeDefinition);
-
- public BaseRouteManager(Environment environment, RouteRepository routeRepository) {
- this.environment = environment;
- ZookeeperContext.setEnvironment(environment);
- this.routeRepository = routeRepository;
- this.routeRootPath = ZookeeperContext.getRouteRootPath();
- this.createRouteRootPath(this.routeRootPath);
- }
-
- @Override
- public void refresh() {
- this.refreshRouteInfo();
- }
-
- protected void refreshRouteInfo() {
- try {
- this.watchServiceChange(routeRootPath);
- } catch (Exception e) {
- log.error("刷新路由配置失败", e);
- throw new IllegalStateException("刷新路由配置失败");
- }
- }
-
- protected void createRouteRootPath(String routeRootPath) {
- try {
- ZookeeperContext.createPath(routeRootPath, "");
- } catch (Exception e) {
- log.error("创建路由根节点失败", e);
- throw new IllegalStateException("创建路由根节点失败");
- }
- }
-
- /**
- * 监听微服务更改
- *
- * @param rootPath
- * @throws Exception
- */
- protected void watchServiceChange(String rootPath) throws Exception {
- ZookeeperContext.getChildrenAndListen(rootPath, childDataList -> {
- log.info("========== 加载路由信息 ==========");
- log.info("{} # 路由根节点", rootPath);
- for (ChildData childData : childDataList) {
- String serviceNodeData = new String(childData.getData());
- R serviceRouteInfo = JSON.parseObject(serviceNodeData, getServiceRouteInfoClass());
- String servicePath = childData.getPath();
- log.info("\t{} # service节点,节点数据:{}", servicePath, serviceNodeData);
- try {
- this.loadServiceRouteItem(serviceRouteInfo, servicePath);
- } catch (Exception e) {
- log.error("加载路由信息失败,servicePath:{}", servicePath, e);
- }
- }
- }, (client, event) -> {
- PathChildrenCacheEvent.Type type = event.getType();
- synchronized (type) {
- // 通过判断event type的方式来实现不同事件的触发
- if (PathChildrenCacheEvent.Type.CHILD_ADDED.equals(type)) {
- String serviceNodeData = new String(event.getData().getData());
- R serviceRouteInfo = JSON.parseObject(serviceNodeData, getServiceRouteInfoClass());
- // 添加子节点时触发
- String servicePath = event.getData().getPath();
- log.info("新增serviceId节点:{},节点数据:{}", servicePath, serviceNodeData);
- this.watchRouteItems(serviceRouteInfo, servicePath);
- } else if (PathChildrenCacheEvent.Type.CHILD_UPDATED.equals(type)) {
- // 修改子节点数据时触发,暂时没有什么操作
- String nodeData = new String(event.getData().getData());
- log.info("修改serviceId节点:{},节点数据:{}", event.getData().getPath(), nodeData);
- } else if (PathChildrenCacheEvent.Type.CHILD_REMOVED.equals(type)) {
- // 删除service节点
- String nodeData = new String(event.getData().getData());
- log.info("删除serviceId节点:{},节点数据:{}", event.getData().getPath(), nodeData);
- R serviceRouteInfo = JSON.parseObject(nodeData, getServiceRouteInfoClass());
- routeRepository.deleteAll(serviceRouteInfo.getServiceId());
- }
- }
- });
- }
-
- /**
- * 加载service下的路由信息
- *
- * @param servicePath
- */
- protected void loadServiceRouteItem(R serviceRouteInfo, String servicePath) throws Exception {
- ZookeeperContext.getChildrenData(servicePath, childDataList -> {
- for (ChildData childData : childDataList) {
- String routeItemPath = childData.getPath();
- byte[] routeItemData = childData.getData();
- String routeDataJson = buildZookeeperData(routeItemData);
- log.info("\t\t{} # 路由节点,节点数据:{}", routeItemPath, routeDataJson);
- this.saveRouteItem(serviceRouteInfo, routeDataJson);
- }
- });
- this.watchRouteItems(serviceRouteInfo, servicePath);
- }
-
-
- /**
- * 监听serviceId目录下面的子节点
- *
- * @param serviceRouteInfo
- * @param servicePath serviceId节点
- */
- protected void watchRouteItems(R serviceRouteInfo, String servicePath) throws Exception {
- log.info("监听{}下子节点增删改", servicePath);
- // 添加事件监听器
- ZookeeperContext.listenChildren(servicePath, (client, event) -> {
- PathChildrenCacheEvent.Type type = event.getType();
- synchronized (type) {
- // 通过判断event type的方式来实现不同事件的触发
- if (PathChildrenCacheEvent.Type.CHILD_ADDED.equals(type)) {
- // 新增单个路由
- String routeDataJson = buildZookeeperData(event.getData().getData());
- log.info("新增单个路由,serviceId:{}, 路由数据:{}", serviceRouteInfo.getServiceId(), routeDataJson);
- saveRouteItem(serviceRouteInfo, routeDataJson);
- } else if (PathChildrenCacheEvent.Type.CHILD_UPDATED.equals(type)) {
- // 修改单个路由
- String routeDataJson = buildZookeeperData(event.getData().getData());
- log.info("修改单个路由,serviceId:{}, 路由数据:{}", serviceRouteInfo.getServiceId(), routeDataJson);
- updateRouteItem(serviceRouteInfo, routeDataJson);
- } else if (PathChildrenCacheEvent.Type.CHILD_REMOVED.equals(type)) {
- // 删除单个路由
- String routeDataJson = buildZookeeperData(event.getData().getData());
- log.info("删除单个路由,serviceId:{}, 路由数据:{}", serviceRouteInfo.getServiceId(), routeDataJson);
- deleteRouteItem(serviceRouteInfo, routeDataJson);
- }
- }
- });
-
- }
-
- protected void saveRouteItem(R serviceRouteInfo, String nodeDataJson) {
- T routeDefinition = getRouteDefinition(serviceRouteInfo, nodeDataJson);
- routeRepository.add(routeDefinition);
- }
-
- protected void updateRouteItem(R serviceRouteInfo, String nodeDataJson) {
- T routeDefinition = getRouteDefinition(serviceRouteInfo, nodeDataJson);
- routeRepository.update(routeDefinition);
- }
-
- protected void deleteRouteItem(R serviceRouteInfo, String nodeDataJson) {
- E routeDefinitionItem = getRouteDefinitionItem(nodeDataJson);
- routeRepository.delete(routeDefinitionItem.getId());
- }
-
- protected T getRouteDefinition(R serviceRouteInfo, String nodeDataJson) {
- E routeDefinitionItem = getRouteDefinitionItem(nodeDataJson);
- T routeDefinition = buildRouteDefinition(serviceRouteInfo, routeDefinitionItem);
- return routeDefinition;
- }
-
- protected E getRouteDefinitionItem(String nodeDataJson) {
- return JSON.parseObject(nodeDataJson, getRouteDefinitionClass());
- }
-
- protected String buildZookeeperData(byte[] data) {
- return new String(data);
- }
-
-}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ManagerContext.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ManagerContext.java
deleted file mode 100644
index aa99921f..00000000
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ManagerContext.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.gitee.sop.gatewaycommon.manager;
-
-import org.springframework.beans.BeansException;
-import org.springframework.context.ApplicationContext;
-
-/**
- * @author tanghc
- */
-public class ManagerContext {
-
- private static ApplicationContext ctx;
-
- public static void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
- ctx = applicationContext;
- }
-
- public static T getManager(Class clazz) {
- return ctx.getBean(clazz);
- }
-
- public static ApplicationContext getApplicationContext() {
- return ctx;
- }
-}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RouteLoader.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RouteLoader.java
new file mode 100644
index 00000000..ba4566fe
--- /dev/null
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RouteLoader.java
@@ -0,0 +1,12 @@
+package com.gitee.sop.gatewaycommon.manager;
+
+import com.gitee.sop.gatewaycommon.bean.ServiceRouteInfo;
+
+/**
+ * @author tanghc
+ */
+public interface RouteLoader {
+ void load(ServiceRouteInfo serviceRouteInfo);
+
+ void remove(String serviceId);
+}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RouteManager.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RouteManager.java
index b443974e..fd4eba19 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RouteManager.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RouteManager.java
@@ -4,6 +4,7 @@ package com.gitee.sop.gatewaycommon.manager;
* 管理各服务路由信息
* @author tanghc
*/
+@Deprecated
public interface RouteManager {
/**
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RoutePermissionManager.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RoutePermissionManager.java
deleted file mode 100644
index df9a63f9..00000000
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RoutePermissionManager.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.gitee.sop.gatewaycommon.manager;
-
-import com.gitee.sop.gatewaycommon.bean.IsvRoutePermission;
-
-/**
- * @author tanghc
- */
-public interface RoutePermissionManager {
- /**
- * 加载路由授权
- */
- void load();
-
- /**
- * 更新路由授权信息
- *
- * @param isvRoutePermission 授权信息
- */
- void update(IsvRoutePermission isvRoutePermission);
-}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ServiceRoutesLoader.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ServiceRoutesLoader.java
new file mode 100644
index 00000000..ad28c439
--- /dev/null
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ServiceRoutesLoader.java
@@ -0,0 +1,118 @@
+package com.gitee.sop.gatewaycommon.manager;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.nacos.api.config.ConfigService;
+import com.alibaba.nacos.api.exception.NacosException;
+import com.alibaba.nacos.api.naming.NamingService;
+import com.alibaba.nacos.api.naming.pojo.Instance;
+import com.alibaba.nacos.api.naming.pojo.ServiceInfo;
+import com.gitee.sop.gatewaycommon.bean.NacosConfigs;
+import com.gitee.sop.gatewaycommon.bean.ServiceRouteInfo;
+import com.gitee.sop.gatewaycommon.bean.TargetRoute;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.alibaba.nacos.NacosConfigProperties;
+import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.DigestUtils;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * 发现新服务,更新路由信息
+ *
+ * @author tanghc
+ */
+@Slf4j
+public class ServiceRoutesLoader {
+
+ private static final String SECRET = "a3d9sf!1@odl90zd>fkASwq";
+
+ private static final int FIVE_SECONDS = 1000 * 5;
+
+ @Autowired
+ private NacosDiscoveryProperties nacosDiscoveryProperties;
+
+ @Autowired
+ private NacosConfigProperties nacosConfigProperties;
+
+ @Autowired
+ private BaseRouteCache baseRouteCache;
+
+ private RestTemplate restTemplate = new RestTemplate();
+
+ private volatile long lastUpdateTime;
+
+ public synchronized void load(ApplicationEvent event) {
+ long now = System.currentTimeMillis();
+ // 5秒内只能执行一次,解决重启应用连续加载4次问题
+ if (now - lastUpdateTime < FIVE_SECONDS) {
+ return;
+ }
+ lastUpdateTime = now;
+ NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
+ List subscribes = null;
+ try {
+ subscribes = namingService.getSubscribeServices();
+ } catch (NacosException e) {
+ log.error("namingService.getSubscribeServices()错误", e);
+ }
+ if (CollectionUtils.isEmpty(subscribes)) {
+ return;
+ }
+ // subscribe
+ String thisServiceId = nacosDiscoveryProperties.getService();
+ ConfigService configService = nacosConfigProperties.configServiceInstance();
+ for (ServiceInfo serviceInfo : subscribes) {
+ String serviceName = serviceInfo.getName();
+ // 如果是本机服务,跳过
+ if (Objects.equals(thisServiceId, serviceName)) {
+ continue;
+ }
+ try {
+ String dataId = NacosConfigs.getRouteDataId(serviceName);
+ String groupId = NacosConfigs.GROUP_ROUTE;
+ List allInstances = namingService.getAllInstances(serviceName);
+ if (CollectionUtils.isEmpty(allInstances)) {
+ log.info("{}服务下线,删除路由信息", serviceName);
+ // 如果没有服务列表,则删除所有路由信息
+ baseRouteCache.remove(serviceName);
+ configService.removeConfig(dataId, groupId);
+ } else {
+ for (Instance instance : allInstances) {
+ log.info("加载服务路由,instance:{}", instance);
+ String url = getRouteRequestUrl(instance);
+ ResponseEntity responseEntity = restTemplate.getForEntity(url, String.class);
+ if (responseEntity.getStatusCode() == HttpStatus.OK) {
+ String body = responseEntity.getBody();
+ log.debug("加载{}路由,路由信息:{}", serviceName, body);
+ ServiceRouteInfo serviceRouteInfo = JSON.parseObject(body, ServiceRouteInfo.class);
+ baseRouteCache.load(serviceRouteInfo);
+ configService.publishConfig(dataId, groupId, body);
+ }
+ }
+ }
+ } catch (NacosException e) {
+ log.error("选择服务实例失败,serviceName:{}", serviceName, e);
+ }
+ }
+ }
+
+ private static String getRouteRequestUrl(Instance instance) {
+ String query = buildQuery(SECRET);
+ return "http://" + instance.getIp() + ":" + instance.getPort() + "/sop/routes" + query;
+ }
+
+ private static String buildQuery(String secret) {
+ String time = String.valueOf(System.currentTimeMillis());
+ String source = secret + time + secret;
+ String sign = DigestUtils.md5DigestAsHex(source.getBytes());
+ return "?time=" + time + "&sign=" + sign;
+ }
+
+}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ZookeeperContext.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ZookeeperContext.java
deleted file mode 100644
index b7672836..00000000
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ZookeeperContext.java
+++ /dev/null
@@ -1,252 +0,0 @@
-package com.gitee.sop.gatewaycommon.manager;
-
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.lang.math.NumberUtils;
-import org.apache.curator.framework.CuratorFramework;
-import org.apache.curator.framework.CuratorFrameworkFactory;
-import org.apache.curator.framework.recipes.cache.ChildData;
-import org.apache.curator.framework.recipes.cache.NodeCache;
-import org.apache.curator.framework.recipes.cache.NodeCacheListener;
-import org.apache.curator.framework.recipes.cache.PathChildrenCache;
-import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;
-import org.apache.curator.retry.ExponentialBackoffRetry;
-import org.springframework.core.env.Environment;
-import org.springframework.util.Assert;
-
-import java.util.List;
-import java.util.function.Consumer;
-
-import static com.gitee.sop.gatewaycommon.bean.SopConstants.SOP_MSG_CHANNEL_PATH;
-import static com.gitee.sop.gatewaycommon.bean.SopConstants.SOP_SERVICE_ROUTE_PATH;
-
-/**
- * @author tanghc
- */
-@Slf4j
-public class ZookeeperContext {
-
- private static CuratorFramework client;
-
- private static Environment environment;
-
- public static void setEnvironment(Environment environment) {
- Assert.notNull(environment, "environment不能为null");
- ZookeeperContext.environment = environment;
- initZookeeperClient();
- }
-
- public synchronized static void initZookeeperClient() {
- if (client != null) {
- return;
- }
- setClient(createClient());
- }
-
- public static CuratorFramework createClient() {
- String zookeeperServerAddr = environment.getProperty("spring.cloud.zookeeper.connect-string");
- if (StringUtils.isBlank(zookeeperServerAddr)) {
- throw new RuntimeException("未指定spring.cloud.zookeeper.connect-string参数");
- }
- String baseSleepTimeMs = environment.getProperty("spring.cloud.zookeeper.baseSleepTimeMs");
- String maxRetries = environment.getProperty("spring.cloud.zookeeper.maxRetries");
- log.info("初始化zookeeper客户端,zookeeperServerAddr:{}, baseSleepTimeMs:{}, maxRetries:{}",
- zookeeperServerAddr, baseSleepTimeMs, maxRetries);
- CuratorFramework client = CuratorFrameworkFactory.builder()
- .connectString(zookeeperServerAddr)
- .retryPolicy(new ExponentialBackoffRetry(NumberUtils.toInt(baseSleepTimeMs, 3000), NumberUtils.toInt(maxRetries, 3)))
- .build();
-
- client.start();
- return client;
- }
-
- public static String getRouteRootPath() {
- return SOP_SERVICE_ROUTE_PATH;
- }
-
- public static String getIsvInfoChannelPath() {
- return SOP_MSG_CHANNEL_PATH + "/isvinfo";
- }
-
- public static String getServiceGrayChannelPath() {
- return SOP_MSG_CHANNEL_PATH + "/gray";
- }
-
- public static String getIsvRoutePermissionChannelPath() {
- return SOP_MSG_CHANNEL_PATH + "/isv-route-permission";
- }
-
- public static String getRouteConfigChannelPath() {
- return SOP_MSG_CHANNEL_PATH + "/route-conf";
- }
-
- public static String getLimitConfigChannelPath() {
- return SOP_MSG_CHANNEL_PATH + "/limit-conf";
- }
-
- public static String getIpBlacklistChannelPath() {
- return SOP_MSG_CHANNEL_PATH + "/ipblacklist-conf";
- }
-
- public static CuratorFramework getClient() {
- return client;
- }
-
- public static void setClient(CuratorFramework client) {
- ZookeeperContext.client = client;
- }
-
- /**
- * 新建或保存节点
- *
- * @param path
- * @param data
- * @return 返回path
- * @throws Exception
- */
- public static String createOrUpdateData(String path, String data) throws Exception {
- return getClient().create()
- // 如果节点存在则Curator将会使用给出的数据设置这个节点的值
- .orSetData()
- // 如果指定节点的父节点不存在,则Curator将会自动级联创建父节点
- .creatingParentContainersIfNeeded()
- .forPath(path, data.getBytes());
- }
-
- /**
- * 更新节点
- * @param path
- * @param data
- * @throws Exception
- */
- public static void updatePath(String path, String data) throws Exception {
- getClient().setData().forPath(path, data.getBytes());
- }
-
- /**
- * 创建path,如果path存在不报错,静默返回path名称
- *
- * @param path
- * @param data
- * @return
- * @throws Exception
- */
- public static String createPath(String path, String data) throws Exception {
- if (isPathExist(path)) {
- return path;
- }
- return getClient().create()
- // 如果指定节点的父节点不存在,则Curator将会自动级联创建父节点
- .creatingParentContainersIfNeeded()
- .forPath(path, data.getBytes());
- }
-
- public static boolean isPathExist(String path) {
- try {
- return client.checkExists().forPath(path) != null;
- } catch (Exception e) {
- return false;
- }
- }
-
- /**
- * 监听一个节点
- *
- * @param path
- * @param onChange 节点修改后触发
- * @return 返回path
- * @throws Exception
- */
- public static String listenPath(String path, Consumer onChange) throws Exception {
- String ret = createOrUpdateData(path, "{}");
- final NodeCache cache = new NodeCache(client, path, false);
- cache.getListenable().addListener(new NodeCacheListener() {
- @Override
- public void nodeChanged() throws Exception {
- onChange.accept(cache);
- }
- });
- cache.start();
- return ret;
- }
-
- /**
- * 获取子节点信息并监听子节点
- *
- * @param parentPath 父节点路径
- * @param listConsumer 子节点数据
- * @param listener 监听事件
- * @throws Exception
- */
- public static void getChildrenAndListen(String parentPath, Consumer> listConsumer, PathChildrenCacheListener listener) throws Exception {
- // 为子节点添加watcher
- // PathChildrenCache: 监听数据节点的增删改,可以设置触发的事件
- PathChildrenCache childrenCache = new PathChildrenCache(client, parentPath, true);
-
- /**
- * StartMode: 初始化方式
- * POST_INITIALIZED_EVENT:异步初始化,初始化之后会触发事件
- * NORMAL:异步初始化
- * BUILD_INITIAL_CACHE:同步初始化
- */
- childrenCache.start(PathChildrenCache.StartMode.BUILD_INITIAL_CACHE);
-
- // 列出子节点数据列表,需要使用BUILD_INITIAL_CACHE同步初始化模式才能获得,异步是获取不到的
- List childDataList = childrenCache.getCurrentData();
- listConsumer.accept(childDataList);
- log.info("监听子节点增删改,监听路径:{}", parentPath);
- // 监听根节点下面的子节点
- childrenCache.getListenable().addListener(listener);
- }
-
- /**
- * 获取子节点信息
- *
- * @param parentPath 父节点路径
- * @param listConsumer 子节点数据
- * @throws Exception
- */
- public static void getChildrenData(String parentPath, Consumer> listConsumer) throws Exception {
- // 为子节点添加watcher
- // PathChildrenCache: 监听数据节点的增删改,可以设置触发的事件
- PathChildrenCache childrenCache = new PathChildrenCache(client, parentPath, true);
-
- /**
- * StartMode: 初始化方式
- * POST_INITIALIZED_EVENT:异步初始化,初始化之后会触发事件
- * NORMAL:异步初始化
- * BUILD_INITIAL_CACHE:同步初始化
- */
- childrenCache.start(PathChildrenCache.StartMode.BUILD_INITIAL_CACHE);
-
- // 列出子节点数据列表,需要使用BUILD_INITIAL_CACHE同步初始化模式才能获得,异步是获取不到的
- List childDataList = childrenCache.getCurrentData();
- listConsumer.accept(childDataList);
- childrenCache.close();
- }
-
- /**
- * 监听子节点的增删改
- *
- * @param parentPath 父节点路径
- * @param listener
- * @throws Exception
- */
- public static void listenChildren(String parentPath, PathChildrenCacheListener listener) throws Exception {
- // 为子节点添加watcher
- // PathChildrenCache: 监听数据节点的增删改,可以设置触发的事件
- PathChildrenCache childrenCache = new PathChildrenCache(client, parentPath, true);
-
- /**
- * StartMode: 初始化方式
- * POST_INITIALIZED_EVENT:异步初始化,初始化之后会触发事件
- * NORMAL:异步初始化
- * BUILD_INITIAL_CACHE:同步初始化
- */
- childrenCache.start(PathChildrenCache.StartMode.BUILD_INITIAL_CACHE);
- // 监听根节点下面的子节点
- childrenCache.getListenable().addListener(listener);
- }
-
-}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/BaseParamBuilder.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/BaseParamBuilder.java
index 4518ff89..6da65c17 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/BaseParamBuilder.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/BaseParamBuilder.java
@@ -1,6 +1,6 @@
package com.gitee.sop.gatewaycommon.param;
-import com.gitee.sop.gatewaycommon.bean.BaseRouteDefinition;
+import com.gitee.sop.gatewaycommon.bean.GatewayRouteDefinition;
import com.gitee.sop.gatewaycommon.bean.TargetRoute;
import com.gitee.sop.gatewaycommon.manager.RouteRepository;
import com.gitee.sop.gatewaycommon.manager.RouteRepositoryContext;
@@ -65,7 +65,7 @@ public abstract class BaseParamBuilder implements ParamBuilder {
TargetRoute targetRoute = routeRepository.get(nameVersion);
Integer ignoreValidate = Optional.ofNullable(targetRoute)
.map(t -> t.getRouteDefinition())
- .map(BaseRouteDefinition::getIgnoreValidate)
+ .map(GatewayRouteDefinition::getIgnoreValidate)
// 默认不忽略
.orElse(BooleanUtils.toInteger(false));
apiParam.setIgnoreValidate(BooleanUtils.toBoolean(ignoreValidate));
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/BaseExecutorAdapter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/BaseExecutorAdapter.java
index fff6b09a..0b011636 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/BaseExecutorAdapter.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/BaseExecutorAdapter.java
@@ -4,10 +4,10 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.gitee.sop.gatewaycommon.bean.ApiConfig;
import com.gitee.sop.gatewaycommon.bean.ApiContext;
-import com.gitee.sop.gatewaycommon.bean.BaseRouteDefinition;
-import com.gitee.sop.gatewaycommon.bean.BaseServiceRouteInfo;
import com.gitee.sop.gatewaycommon.bean.ErrorDefinition;
+import com.gitee.sop.gatewaycommon.bean.GatewayRouteDefinition;
import com.gitee.sop.gatewaycommon.bean.Isv;
+import com.gitee.sop.gatewaycommon.bean.ServiceRouteInfo;
import com.gitee.sop.gatewaycommon.bean.SopConstants;
import com.gitee.sop.gatewaycommon.bean.TargetRoute;
import com.gitee.sop.gatewaycommon.manager.RouteRepositoryContext;
@@ -139,7 +139,7 @@ public abstract class BaseExecutorAdapter implements ResultExecutor
return defaultSetting;
}
ApiInfo apiInfo = this.getApiInfo(request);
- BaseRouteDefinition baseRouteDefinition = apiInfo.baseRouteDefinition;
+ GatewayRouteDefinition baseRouteDefinition = apiInfo.gatewayRouteDefinition;
return Optional.ofNullable(baseRouteDefinition)
.map(routeDefinition -> {
int mergeResult = baseRouteDefinition.getMergeResult();
@@ -157,10 +157,10 @@ public abstract class BaseExecutorAdapter implements ResultExecutor
String serviceId = Optional.ofNullable(targetRoute)
.flatMap(route -> Optional.ofNullable(route.getServiceRouteInfo()))
- .map(BaseServiceRouteInfo::getServiceId)
+ .map(ServiceRouteInfo::getServiceId)
.orElse(SopConstants.UNKNOWN_SERVICE);
- BaseRouteDefinition baseRouteDefinition = Optional.ofNullable(targetRoute)
+ GatewayRouteDefinition baseRouteDefinition = Optional.ofNullable(targetRoute)
.map(route -> route.getRouteDefinition())
.orElse(null);
@@ -168,7 +168,7 @@ public abstract class BaseExecutorAdapter implements ResultExecutor
apiInfo.name = name;
apiInfo.version = version;
apiInfo.serviceId = serviceId;
- apiInfo.baseRouteDefinition = baseRouteDefinition;
+ apiInfo.gatewayRouteDefinition = baseRouteDefinition;
return apiInfo;
}
@@ -276,7 +276,7 @@ public abstract class BaseExecutorAdapter implements ResultExecutor
private String name;
private String version;
private String serviceId;
- private BaseRouteDefinition baseRouteDefinition;
+ private GatewayRouteDefinition gatewayRouteDefinition;
}
enum ErrorType {
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/validate/ApiValidator.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/validate/ApiValidator.java
index fccd5c23..a8ed1357 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/validate/ApiValidator.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/validate/ApiValidator.java
@@ -2,7 +2,7 @@ package com.gitee.sop.gatewaycommon.validate;
import com.gitee.sop.gatewaycommon.bean.ApiConfig;
import com.gitee.sop.gatewaycommon.bean.ApiContext;
-import com.gitee.sop.gatewaycommon.bean.BaseRouteDefinition;
+import com.gitee.sop.gatewaycommon.bean.GatewayRouteDefinition;
import com.gitee.sop.gatewaycommon.bean.Isv;
import com.gitee.sop.gatewaycommon.bean.RouteConfig;
import com.gitee.sop.gatewaycommon.bean.TargetRoute;
@@ -216,7 +216,7 @@ public class ApiValidator implements Validator {
protected void checkPermission(ApiParam apiParam) {
String routeId = apiParam.fetchNameVersion();
TargetRoute targetRoute = RouteRepositoryContext.getRouteRepository().get(routeId);
- BaseRouteDefinition routeDefinition = targetRoute.getRouteDefinition();
+ GatewayRouteDefinition routeDefinition = targetRoute.getRouteDefinition();
boolean needCheckPermission = BooleanUtils.toBoolean(routeDefinition.getPermission());
if (needCheckPermission) {
String appKey = apiParam.fetchAppKey();
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/BaseZuulConfiguration.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/BaseZuulConfiguration.java
index f0470ec0..07811339 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/BaseZuulConfiguration.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/BaseZuulConfiguration.java
@@ -15,8 +15,8 @@ import com.gitee.sop.gatewaycommon.zuul.filter.PreValidateFilter;
import com.gitee.sop.gatewaycommon.zuul.filter.PreVersionDecisionFilter;
import com.gitee.sop.gatewaycommon.zuul.filter.Servlet30WrapperFilterExt;
import com.gitee.sop.gatewaycommon.zuul.route.SopRouteLocator;
+import com.gitee.sop.gatewaycommon.zuul.route.ZuulRouteCache;
import com.gitee.sop.gatewaycommon.zuul.route.ZuulRouteRepository;
-import com.gitee.sop.gatewaycommon.zuul.route.ZuulZookeeperRouteManager;
import com.netflix.zuul.context.RequestContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@@ -26,7 +26,6 @@ import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.cloud.netflix.zuul.filters.pre.PreDecorationFilter;
import org.springframework.context.annotation.Bean;
-import org.springframework.core.env.Environment;
/**
* @author tanghc
@@ -46,8 +45,7 @@ public class BaseZuulConfiguration extends AbstractConfiguration {
}
/**
- * 路由存储
- * @return
+ * 路由仓库
*/
@Bean
ZuulRouteRepository zuulRouteRepository() {
@@ -89,12 +87,11 @@ public class BaseZuulConfiguration extends AbstractConfiguration {
/**
* 路由管理
- * @param environment
- * @param zuulRouteRepository
+ * @param zuulRouteRepository 路由仓库
*/
@Bean
- ZuulZookeeperRouteManager zuulZookeeperRouteManager(Environment environment, ZuulRouteRepository zuulRouteRepository) {
- return new ZuulZookeeperRouteManager(environment, zuulRouteRepository);
+ ZuulRouteCache zuulRouteLoader(ZuulRouteRepository zuulRouteRepository) {
+ return new ZuulRouteCache(zuulRouteRepository);
}
/**
@@ -126,8 +123,6 @@ public class BaseZuulConfiguration extends AbstractConfiguration {
return new PreVersionDecisionFilter();
}
-
-
/**
* 错误处理扩展
*/
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreRoutePermissionFilter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreRoutePermissionFilter.java
deleted file mode 100644
index c693f9b5..00000000
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreRoutePermissionFilter.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.gitee.sop.gatewaycommon.zuul.filter;
-
-import com.gitee.sop.gatewaycommon.bean.BaseRouteDefinition;
-import com.gitee.sop.gatewaycommon.bean.TargetRoute;
-import com.gitee.sop.gatewaycommon.manager.IsvRoutePermissionManager;
-import com.gitee.sop.gatewaycommon.manager.RouteRepositoryContext;
-import com.gitee.sop.gatewaycommon.message.ErrorEnum;
-import com.gitee.sop.gatewaycommon.param.ApiParam;
-import com.gitee.sop.gatewaycommon.zuul.ZuulContext;
-import com.netflix.zuul.context.RequestContext;
-import com.netflix.zuul.exception.ZuulException;
-import org.apache.commons.lang3.BooleanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-
-/**
- * 路由权限校验,有些接口需要配置权限才能访问。
- * @author tanghc
- * @deprecated 已经整合到ApiValidator中,见ApiValidator.checkPermission()
- */
-@Deprecated
-public class PreRoutePermissionFilter extends BaseZuulFilter {
-
- @Autowired
- private IsvRoutePermissionManager isvRoutePermissionManager;
-
- @Override
- protected FilterType getFilterType() {
- return FilterType.PRE;
- }
-
- @Override
- protected int getFilterOrder() {
- // 放在签名验证后面
- return PRE_ROUTE_PERMISSION_FILTER_ORDER;
- }
-
- @Override
- protected Object doRun(RequestContext requestContext) throws ZuulException {
- ApiParam apiParam = ZuulContext.getApiParam();
- String routeId = apiParam.fetchNameVersion();
- TargetRoute targetRoute = RouteRepositoryContext.getRouteRepository().get(routeId);
- BaseRouteDefinition routeDefinition = targetRoute.getRouteDefinition();
- boolean needCheckPermission = BooleanUtils.toBoolean(routeDefinition.getPermission());
- if (needCheckPermission) {
- String appKey = apiParam.fetchAppKey();
- boolean hasPermission = isvRoutePermissionManager.hasPermission(appKey, routeId);
- if (!hasPermission) {
- throw ErrorEnum.ISV_ROUTE_NO_PERMISSIONS.getErrorMeta().getException();
- }
- }
-
- return null;
- }
-}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/ZuulRouteCache.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/ZuulRouteCache.java
new file mode 100644
index 00000000..e8285ad2
--- /dev/null
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/ZuulRouteCache.java
@@ -0,0 +1,34 @@
+package com.gitee.sop.gatewaycommon.zuul.route;
+
+import com.gitee.sop.gatewaycommon.bean.GatewayRouteDefinition;
+import com.gitee.sop.gatewaycommon.bean.ServiceRouteInfo;
+import com.gitee.sop.gatewaycommon.manager.BaseRouteCache;
+import com.gitee.sop.gatewaycommon.manager.RouteRepository;
+import com.gitee.sop.gatewaycommon.util.RouteUtil;
+import org.springframework.cloud.netflix.zuul.filters.Route;
+
+/**
+ * @author tanghc
+ */
+public class ZuulRouteCache extends BaseRouteCache {
+
+ /** 路由重试 */
+ public static final boolean RETRYABLE = true;
+
+ public ZuulRouteCache(RouteRepository routeRepository) {
+ super(routeRepository);
+ }
+
+ @Override
+ protected ZuulTargetRoute buildRouteDefinition(ServiceRouteInfo serviceRouteInfo, GatewayRouteDefinition gatewayRouteDefinition) {
+ Route route = new Route(
+ gatewayRouteDefinition.getId()
+ , gatewayRouteDefinition.getPath()
+ , RouteUtil.getZuulLocation(gatewayRouteDefinition.getUri())
+ , ""
+ , RETRYABLE
+ , null
+ );
+ return new ZuulTargetRoute(serviceRouteInfo, gatewayRouteDefinition, route);
+ }
+}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/ZuulRouteDefinition.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/ZuulRouteDefinition.java
deleted file mode 100644
index fba3d5ff..00000000
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/ZuulRouteDefinition.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.gitee.sop.gatewaycommon.zuul.route;
-
-import com.gitee.sop.gatewaycommon.bean.BaseRouteDefinition;
-import lombok.Getter;
-import lombok.Setter;
-
-/**
- * @author tanghc
- */
-@Getter
-@Setter
-public class ZuulRouteDefinition extends BaseRouteDefinition {
-}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/ZuulServiceRouteInfo.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/ZuulServiceRouteInfo.java
deleted file mode 100644
index 7e22c1f9..00000000
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/ZuulServiceRouteInfo.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.gitee.sop.gatewaycommon.zuul.route;
-
-import com.gitee.sop.gatewaycommon.bean.BaseServiceRouteInfo;
-
-/**
- * @author tanghc
- */
-public class ZuulServiceRouteInfo extends BaseServiceRouteInfo {
-}
\ No newline at end of file
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/ZuulTargetRoute.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/ZuulTargetRoute.java
index 4d6223a4..00b928f9 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/ZuulTargetRoute.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/ZuulTargetRoute.java
@@ -1,6 +1,8 @@
package com.gitee.sop.gatewaycommon.zuul.route;
import com.gitee.sop.gatewaycommon.bean.AbstractTargetRoute;
+import com.gitee.sop.gatewaycommon.bean.GatewayRouteDefinition;
+import com.gitee.sop.gatewaycommon.bean.ServiceRouteInfo;
import lombok.Getter;
import org.springframework.cloud.netflix.zuul.filters.Route;
@@ -8,9 +10,9 @@ import org.springframework.cloud.netflix.zuul.filters.Route;
* @author tanghc
*/
@Getter
-public class ZuulTargetRoute extends AbstractTargetRoute {
+public class ZuulTargetRoute extends AbstractTargetRoute {
- public ZuulTargetRoute(ZuulServiceRouteInfo baseServiceRouteInfo, ZuulRouteDefinition baseRouteDefinition, Route targetRoute) {
- super(baseServiceRouteInfo, baseRouteDefinition, targetRoute);
+ public ZuulTargetRoute(ServiceRouteInfo serviceRouteInfo, GatewayRouteDefinition routeDefinition, Route targetRoute) {
+ super(serviceRouteInfo, routeDefinition, targetRoute);
}
}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/ZuulZookeeperRouteManager.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/ZuulZookeeperRouteManager.java
deleted file mode 100644
index 3e0cb7b8..00000000
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/ZuulZookeeperRouteManager.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.gitee.sop.gatewaycommon.zuul.route;
-
-import com.gitee.sop.gatewaycommon.manager.BaseRouteManager;
-import com.gitee.sop.gatewaycommon.manager.RouteRepository;
-import com.gitee.sop.gatewaycommon.util.RouteUtil;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.cloud.netflix.zuul.filters.Route;
-import org.springframework.core.env.Environment;
-
-/**
- * 路由内容管理,新增活修改路由
- *
- * @author tanghc
- */
-@Slf4j
-public class ZuulZookeeperRouteManager extends BaseRouteManager {
-
- /** 路由重试 */
- public static final boolean RETRYABLE = true;
-
- public ZuulZookeeperRouteManager(Environment environment, RouteRepository routeRepository) {
- super(environment, routeRepository);
- }
-
- @Override
- protected Class getServiceRouteInfoClass() {
- return ZuulServiceRouteInfo.class;
- }
-
- @Override
- protected Class getRouteDefinitionClass() {
- return ZuulRouteDefinition.class;
- }
-
- @Override
- protected ZuulTargetRoute buildRouteDefinition(ZuulServiceRouteInfo serviceRouteInfo, ZuulRouteDefinition routeDefinition) {
- Route route = new Route(routeDefinition.getId(), routeDefinition.getPath(), RouteUtil.getZuulLocation(routeDefinition.getUri()), "", RETRYABLE, null);
- return new ZuulTargetRoute(serviceRouteInfo, routeDefinition, route);
- }
-}
diff --git a/sop-common/sop-registry-api/pom.xml b/sop-common/sop-registry-api/pom.xml
index a7a89cde..086f59ce 100644
--- a/sop-common/sop-registry-api/pom.xml
+++ b/sop-common/sop-registry-api/pom.xml
@@ -25,7 +25,7 @@
com.alibaba.nacos
nacos-client
- 1.0.1
+ 1.1.3
diff --git a/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceNacos.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceNacos.java
index 03c0614d..9192b947 100644
--- a/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceNacos.java
+++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceNacos.java
@@ -33,7 +33,7 @@ public class RegistryServiceNacos implements RegistryService {
static HttpTool httpTool = new HttpTool();
- @Value("${registry.nacos-server-addr:}")
+ @Value("${nacos.discovery.server-addr:}")
private String nacosAddr;
private NamingService namingService;
diff --git a/sop-common/sop-service-common/pom.xml b/sop-common/sop-service-common/pom.xml
index f22638cb..5fab3da9 100644
--- a/sop-common/sop-service-common/pom.xml
+++ b/sop-common/sop-service-common/pom.xml
@@ -21,6 +21,11 @@
+
+ org.springframework.cloud
+ spring-cloud-alibaba-nacos-discovery
+
+
org.springframework
spring-webmvc
diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/ZookeeperTool.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/ZookeeperTool.java
deleted file mode 100644
index 8130d7f8..00000000
--- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/ZookeeperTool.java
+++ /dev/null
@@ -1,138 +0,0 @@
-package com.gitee.sop.servercommon.bean;
-
-import com.gitee.sop.servercommon.exception.ZookeeperOperationException;
-import com.gitee.sop.servercommon.exception.ZookeeperPathNotExistException;
-import lombok.Getter;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.lang.math.NumberUtils;
-import org.apache.curator.framework.CuratorFramework;
-import org.apache.curator.framework.CuratorFrameworkFactory;
-import org.apache.curator.retry.ExponentialBackoffRetry;
-import org.apache.zookeeper.CreateMode;
-import org.springframework.core.env.Environment;
-
-import java.io.Closeable;
-import java.io.IOException;
-
-
-/**
- * @author tanghc
- */
-@Slf4j
-@Getter
-public class ZookeeperTool implements Closeable {
-
- private CuratorFramework client;
- private Environment environment;
-
- public ZookeeperTool(Environment environment) {
- this.environment = environment;
- initZookeeperClient(environment);
- }
-
- public void initZookeeperClient(Environment environment) {
- String zookeeperServerAddr = environment.getProperty("spring.cloud.zookeeper.connect-string");
- if (StringUtils.isBlank(zookeeperServerAddr)) {
- throw new RuntimeException("未指定spring.cloud.zookeeper.connect-string参数");
- }
- String baseSleepTimeMs = environment.getProperty("spring.cloud.zookeeper.baseSleepTimeMs");
- String maxRetries = environment.getProperty("spring.cloud.zookeeper.maxRetries");
- log.info("初始化zookeeper客户端,zookeeperServerAddr:{}, baseSleepTimeMs:{}, maxRetries:{}",
- zookeeperServerAddr, baseSleepTimeMs, maxRetries);
- CuratorFramework client = CuratorFrameworkFactory.builder()
- .connectString(zookeeperServerAddr)
- .retryPolicy(new ExponentialBackoffRetry(NumberUtils.toInt(baseSleepTimeMs, 3000), NumberUtils.toInt(maxRetries, 3)))
- .build();
-
- client.start();
-
- this.client = client;
- }
-
- /**
- * 获取节点内容
- *
- * @param path
- * @return 返回节点内容
- * @throws ZookeeperPathNotExistException 节点不存在,抛出异常
- */
- public String getData(String path) throws ZookeeperPathNotExistException {
- if (!isPathExist(path)) {
- throw new ZookeeperPathNotExistException("path 不存在, path=" + path);
- }
- try {
- byte[] data = getClient().getData().forPath(path);
- return new String(data);
- } catch (Exception e) {
- throw new ZookeeperOperationException("getData error path=" + path, e);
- }
- }
-
- public boolean isPathExist(String path) {
- try {
- return client.checkExists().forPath(path) != null;
- } catch (Exception e) {
- return false;
- }
- }
-
- /**
- * 创建path,如果path存在不报错,静默返回path名称
- *
- * @param path
- * @param data
- * @return
- * @throws Exception
- */
- public String createPath(String path, String data) throws Exception {
- if (isPathExist(path)) {
- return path;
- }
- return getClient().create()
- // 如果指定节点的父节点不存在,则Curator将会自动级联创建父节点
- .creatingParentContainersIfNeeded()
- .forPath(path, data.getBytes());
- }
-
- /**
- * 创建临时序列节点
- * @param path 节点路径
- * @param data 数据
- * @return 返回节点路径
- * @throws Exception
- */
- public String createOrUpdateEphemeralSequentialPath(String path, String data) throws Exception {
- return getClient().create()
- // 如果节点存在则Curator将会使用给出的数据设置这个节点的值
- .orSetData()
- // 如果指定节点的父节点不存在,则Curator将会自动级联创建父节点
- .creatingParentContainersIfNeeded()
- .withMode(CreateMode.EPHEMERAL_SEQUENTIAL)
- .forPath(path, data.getBytes());
- }
-
- /**
- * 新建或保存节点
- *
- * @param path
- * @param data
- * @return 返回path
- * @throws Exception
- */
- public String createOrUpdateData(String path, String data) throws Exception {
- return getClient().create()
- // 如果节点存在则Curator将会使用给出的数据设置这个节点的值
- .orSetData()
- // 如果指定节点的父节点不存在,则Curator将会自动级联创建父节点
- .creatingParentContainersIfNeeded()
- .forPath(path, data.getBytes());
- }
-
- @Override
- public void close() throws IOException {
- if (this.client != null) {
- this.client.close();
- }
- }
-}
diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/BaseServiceConfiguration.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/BaseServiceConfiguration.java
index 6dcdd549..8f87f45a 100644
--- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/BaseServiceConfiguration.java
+++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/BaseServiceConfiguration.java
@@ -2,18 +2,13 @@ package com.gitee.sop.servercommon.configuration;
import com.gitee.sop.servercommon.bean.ServiceConfig;
import com.gitee.sop.servercommon.interceptor.ServiceContextInterceptor;
-import com.gitee.sop.servercommon.manager.ApiMetaManager;
-import com.gitee.sop.servercommon.manager.DefaultRequestMappingEvent;
-import com.gitee.sop.servercommon.manager.RequestMappingEvent;
-import com.gitee.sop.servercommon.manager.ServiceZookeeperApiMetaManager;
+import com.gitee.sop.servercommon.manager.ServiceRouteController;
import com.gitee.sop.servercommon.mapping.ApiMappingHandlerMapping;
import com.gitee.sop.servercommon.message.ServiceErrorFactory;
import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.annotation.Bean;
-import org.springframework.core.env.Environment;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
@@ -36,9 +31,6 @@ public class BaseServiceConfiguration extends WebMvcConfigurationSupport
ServiceConfig.getInstance().getI18nModules().add("i18n/isp/bizerror");
}
- @Autowired
- private Environment environment;
-
private ApiMappingHandlerMapping apiMappingHandlerMapping = new ApiMappingHandlerMapping();
@Override
@@ -77,19 +69,16 @@ public class BaseServiceConfiguration extends WebMvcConfigurationSupport
return apiMappingHandlerMapping;
}
- protected RequestMappingEvent getRequestMappingEvent(ApiMetaManager apiMetaManager, Environment environment) {
- return new DefaultRequestMappingEvent(apiMetaManager, environment);
- }
-
- protected ApiMetaManager getApiMetaManager(Environment environment) {
- return new ServiceZookeeperApiMetaManager(environment);
- }
-
@Bean
GlobalExceptionHandler globalExceptionHandler() {
return ServiceConfig.getInstance().getGlobalExceptionHandler();
}
+ @Bean
+ ServiceRouteController serviceRouteController() {
+ return new ServiceRouteController();
+ }
+
@PostConstruct
public final void after() {
log.info("-----spring容器加载完毕-----");
@@ -105,9 +94,6 @@ public class BaseServiceConfiguration extends WebMvcConfigurationSupport
@Override
public void run(ApplicationArguments args) throws Exception {
log.info("-----服务器启动完毕-----");
- ApiMetaManager apiMetaManager = getApiMetaManager(environment);
- RequestMappingEvent requestMappingEvent = getRequestMappingEvent(apiMetaManager, environment);
- requestMappingEvent.onRegisterSuccess(apiMappingHandlerMapping);
this.onStartup(args);
}
diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/EasyopenServiceConfiguration.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/EasyopenServiceConfiguration.java
index f0d4b7e1..075db50f 100644
--- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/EasyopenServiceConfiguration.java
+++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/EasyopenServiceConfiguration.java
@@ -6,7 +6,6 @@ import com.gitee.easyopen.util.ReflectionUtil;
import com.gitee.sop.servercommon.bean.ServiceApiInfo;
import com.gitee.sop.servercommon.manager.ApiMetaManager;
import com.gitee.sop.servercommon.manager.DefaultRequestMappingEvent;
-import com.gitee.sop.servercommon.manager.RequestMappingEvent;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
@@ -30,11 +29,6 @@ public class EasyopenServiceConfiguration extends BaseServiceConfiguration {
ApiContext.getApiConfig().setIgnoreValidate(true);
}
- @Override
- protected RequestMappingEvent getRequestMappingEvent(ApiMetaManager apiMetaManager, Environment environment) {
- return new EasyopenRequestMappingEvent(apiMetaManager, environment);
- }
-
class EasyopenRequestMappingEvent extends DefaultRequestMappingEvent {
String prefixPath;
diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/SpringMvcServiceConfiguration.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/SpringMvcServiceConfiguration.java
index 6b76778e..36492179 100644
--- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/SpringMvcServiceConfiguration.java
+++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/SpringMvcServiceConfiguration.java
@@ -1,21 +1,14 @@
package com.gitee.sop.servercommon.configuration;
import com.gitee.sop.servercommon.bean.ServiceConfig;
-import com.gitee.sop.servercommon.manager.ApiMetaManager;
-import com.gitee.sop.servercommon.manager.DefaultRequestMappingEvent;
-import com.gitee.sop.servercommon.manager.RequestMappingEvent;
-import com.gitee.sop.servercommon.manager.ServiceZookeeperApiMetaManager;
import com.gitee.sop.servercommon.mapping.ApiMappingHandlerMapping;
import com.gitee.sop.servercommon.message.ServiceErrorFactory;
import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
-import org.springframework.core.env.Environment;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import javax.annotation.PostConstruct;
-import java.util.concurrent.Executors;
/**
* 提供给springmvc工程
@@ -30,10 +23,6 @@ public class SpringMvcServiceConfiguration {
private ApiMappingHandlerMapping apiMappingHandlerMapping = new ApiMappingHandlerMapping();
- @Autowired
- private Environment environment;
-
-
/**
* 自定义Mapping,详见@ApiMapping
*
@@ -54,20 +43,10 @@ public class SpringMvcServiceConfiguration {
@PostConstruct
public final void after() {
log.info("-----spring容器加载完毕-----");
- Executors.newSingleThreadExecutor().execute(()->{
- uploadRouteToZookeeper();
- });
initMessage();
doAfter();
}
- private void uploadRouteToZookeeper() {
- ApiMetaManager apiMetaManager = new ServiceZookeeperApiMetaManager(environment);
- RequestMappingEvent requestMappingEvent = new DefaultRequestMappingEvent(apiMetaManager, environment);
- requestMappingEvent.onRegisterSuccess(apiMappingHandlerMapping);
- }
-
-
/**
* spring容器加载完毕后执行
*/
diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/exception/ZookeeperOperationException.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/exception/ZookeeperOperationException.java
deleted file mode 100644
index 64823412..00000000
--- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/exception/ZookeeperOperationException.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.gitee.sop.servercommon.exception;
-
-/**
- * @author tanghc
- */
-public class ZookeeperOperationException extends RuntimeException {
-
- public ZookeeperOperationException() {
- }
-
- public ZookeeperOperationException(String message) {
- super(message);
- }
-
- public ZookeeperOperationException(String message, Throwable cause) {
- super(message, cause);
- }
-
- public ZookeeperOperationException(Throwable cause) {
- super(cause);
- }
-
- public ZookeeperOperationException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
- super(message, cause, enableSuppression, writableStackTrace);
- }
-}
diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/exception/ZookeeperPathNotExistException.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/exception/ZookeeperPathNotExistException.java
deleted file mode 100644
index 2b82263e..00000000
--- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/exception/ZookeeperPathNotExistException.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.gitee.sop.servercommon.exception;
-
-/**
- * @author tanghc
- */
-public class ZookeeperPathNotExistException extends Exception {
- public ZookeeperPathNotExistException(String message) {
- super(message);
- }
-}
diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ApiMetaBuilder.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ApiMetaBuilder.java
new file mode 100644
index 00000000..4ca6f95e
--- /dev/null
+++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ApiMetaBuilder.java
@@ -0,0 +1,100 @@
+package com.gitee.sop.servercommon.manager;
+
+import com.gitee.sop.servercommon.bean.ServiceApiInfo;
+import com.gitee.sop.servercommon.bean.ServiceConfig;
+import com.gitee.sop.servercommon.mapping.ApiMappingInfo;
+import com.gitee.sop.servercommon.mapping.ApiMappingRequestCondition;
+import com.gitee.sop.servercommon.mapping.RouteUtil;
+import org.apache.commons.lang3.BooleanUtils;
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.mvc.condition.RequestCondition;
+import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
+import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author tanghc
+ */
+public class ApiMetaBuilder {
+
+ /** 接口名规则:允许字母、数字、点、下划线 */
+ private static final String REGEX_API_NAME = "^[a-zA-Z0-9\\.\\_\\-]+$";
+
+ public ServiceApiInfo getServiceApiInfo(String serviceId, RequestMappingHandlerMapping requestMappingHandlerMapping) {
+ if (serviceId == null) {
+ throw new IllegalArgumentException("请在application.properties中指定spring.application.name属性");
+ }
+ List apis = this.buildApiMetaList(requestMappingHandlerMapping);
+ // 排序
+ apis.sort(Comparator.comparing(ServiceApiInfo.ApiMeta::fetchNameVersion));
+
+ ServiceApiInfo serviceApiInfo = new ServiceApiInfo();
+ serviceApiInfo.setServiceId(serviceId);
+ serviceApiInfo.setApis(apis);
+
+ return serviceApiInfo;
+ }
+
+ protected List buildApiMetaList(RequestMappingHandlerMapping requestMappingHandlerMapping) {
+ Map handlerMethods = requestMappingHandlerMapping.getHandlerMethods();
+ Set requestMappingInfos = handlerMethods.keySet();
+ List store = new ArrayList<>();
+ List apis = new ArrayList<>(requestMappingInfos.size());
+
+ for (Map.Entry handlerMethodEntry : handlerMethods.entrySet()) {
+ ServiceApiInfo.ApiMeta apiMeta = this.buildApiMeta(handlerMethodEntry);
+ if (apiMeta == null) {
+ continue;
+ }
+ String key = apiMeta.fetchNameVersion();
+ if (store.contains(key)) {
+ throw new IllegalArgumentException("重复申明接口,请检查path和version,path:" + apiMeta.getPath() + ", version:" + apiMeta.getVersion());
+ } else {
+ store.add(key);
+ }
+ apis.add(apiMeta);
+ }
+ return apis;
+ }
+
+ protected ServiceApiInfo.ApiMeta buildApiMeta(Map.Entry handlerMethodEntry) {
+ RequestMappingInfo requestMappingInfo = handlerMethodEntry.getKey();
+ Set patterns = requestMappingInfo.getPatternsCondition().getPatterns();
+ RequestCondition> customCondition = requestMappingInfo.getCustomCondition();
+ if (customCondition instanceof ApiMappingRequestCondition) {
+ ApiMappingRequestCondition condition = (ApiMappingRequestCondition) customCondition;
+ ApiMappingInfo apiMappingInfo = condition.getApiMappingInfo();
+ String name = apiMappingInfo.getName();
+ String version = apiMappingInfo.getVersion();
+ // 方法完整的path,如: /goods/listGoods,/users/user/get
+ String path = patterns.iterator().next();
+ // 不是ApiMapping注解的接口,name属性是null
+ if (name == null || ServiceConfig.getInstance().isWebappMode()) {
+ name = buildName(path);
+ }
+ this.checkApiName(name);
+ ServiceApiInfo.ApiMeta apiMeta = new ServiceApiInfo.ApiMeta(name, path, version);
+ apiMeta.setIgnoreValidate(BooleanUtils.toInteger(apiMappingInfo.isIgnoreValidate()));
+ apiMeta.setMergeResult(BooleanUtils.toInteger(apiMappingInfo.isMergeResult()));
+ apiMeta.setPermission(BooleanUtils.toInteger(apiMappingInfo.isPermission()));
+ return apiMeta;
+ }
+ return null;
+ }
+
+ protected void checkApiName(String name) {
+ if (!name.matches(REGEX_API_NAME)) {
+ throw new IllegalArgumentException("接口名称只允许【字母、数字、点(.)、下划线(_)、减号(-)】,错误接口:" + name);
+ }
+ }
+
+
+ protected String buildName(String path) {
+ return RouteUtil.buildApiName(path);
+ }
+}
diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/DefaultRequestMappingEvent.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/DefaultRequestMappingEvent.java
index 4b3474db..3e3a59bb 100644
--- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/DefaultRequestMappingEvent.java
+++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/DefaultRequestMappingEvent.java
@@ -1,32 +1,15 @@
package com.gitee.sop.servercommon.manager;
import com.gitee.sop.servercommon.bean.ServiceApiInfo;
-import com.gitee.sop.servercommon.bean.ServiceConfig;
-import com.gitee.sop.servercommon.mapping.ApiMappingInfo;
-import com.gitee.sop.servercommon.mapping.ApiMappingRequestCondition;
-import com.gitee.sop.servercommon.mapping.RouteUtil;
import lombok.Getter;
-import org.apache.commons.lang3.BooleanUtils;
import org.springframework.core.env.Environment;
-import org.springframework.web.method.HandlerMethod;
-import org.springframework.web.servlet.mvc.condition.RequestCondition;
-import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
/**
* @author tanghc
*/
@Getter
-public class DefaultRequestMappingEvent implements RequestMappingEvent {
-
- /** 接口名规则:允许字母、数字、点、下划线 */
- private static final String REGEX_API_NAME = "^[a-zA-Z0-9\\.\\_\\-]+$";
+public class DefaultRequestMappingEvent extends ApiMetaBuilder implements RequestMappingEvent {
private ApiMetaManager apiMetaManager;
private Environment environment;
@@ -39,76 +22,8 @@ public class DefaultRequestMappingEvent implements RequestMappingEvent {
@Override
public void onRegisterSuccess(RequestMappingHandlerMapping requestMappingHandlerMapping) {
String serviceId = environment.getProperty("spring.application.name");
- if (serviceId == null) {
- throw new IllegalArgumentException("请在application.properties中指定spring.application.name属性");
- }
- List apis = this.buildApiMetaList(requestMappingHandlerMapping);
- // 排序
- apis.sort(Comparator.comparing(ServiceApiInfo.ApiMeta::fetchNameVersion));
-
- ServiceApiInfo serviceApiInfo = new ServiceApiInfo();
- serviceApiInfo.setServiceId(serviceId);
- serviceApiInfo.setApis(apis);
-
+ ServiceApiInfo serviceApiInfo = getServiceApiInfo(serviceId, requestMappingHandlerMapping);
apiMetaManager.uploadApi(serviceApiInfo);
}
- protected List buildApiMetaList(RequestMappingHandlerMapping requestMappingHandlerMapping) {
- Map handlerMethods = requestMappingHandlerMapping.getHandlerMethods();
- Set requestMappingInfos = handlerMethods.keySet();
- List store = new ArrayList<>();
- List apis = new ArrayList<>(requestMappingInfos.size());
-
- for (Map.Entry handlerMethodEntry : handlerMethods.entrySet()) {
- ServiceApiInfo.ApiMeta apiMeta = this.buildApiMeta(handlerMethodEntry);
- if (apiMeta == null) {
- continue;
- }
- String key = apiMeta.fetchNameVersion();
- if (store.contains(key)) {
- throw new IllegalArgumentException("重复申明接口,请检查path和version,path:" + apiMeta.getPath() + ", version:" + apiMeta.getVersion());
- } else {
- store.add(key);
- }
- apis.add(apiMeta);
- }
- return apis;
- }
-
- protected ServiceApiInfo.ApiMeta buildApiMeta(Map.Entry handlerMethodEntry) {
- RequestMappingInfo requestMappingInfo = handlerMethodEntry.getKey();
- Set patterns = requestMappingInfo.getPatternsCondition().getPatterns();
- RequestCondition> customCondition = requestMappingInfo.getCustomCondition();
- if (customCondition instanceof ApiMappingRequestCondition) {
- ApiMappingRequestCondition condition = (ApiMappingRequestCondition) customCondition;
- ApiMappingInfo apiMappingInfo = condition.getApiMappingInfo();
- String name = apiMappingInfo.getName();
- String version = apiMappingInfo.getVersion();
- // 方法完整的path,如: /goods/listGoods,/users/user/get
- String path = patterns.iterator().next();
- // 不是ApiMapping注解的接口,name属性是null
- if (name == null || ServiceConfig.getInstance().isWebappMode()) {
- name = buildName(path);
- }
- this.checkApiName(name);
- ServiceApiInfo.ApiMeta apiMeta = new ServiceApiInfo.ApiMeta(name, path, version);
- apiMeta.setIgnoreValidate(BooleanUtils.toInteger(apiMappingInfo.isIgnoreValidate()));
- apiMeta.setMergeResult(BooleanUtils.toInteger(apiMappingInfo.isMergeResult()));
- apiMeta.setPermission(BooleanUtils.toInteger(apiMappingInfo.isPermission()));
- return apiMeta;
- }
- return null;
- }
-
- protected void checkApiName(String name) {
- if (!name.matches(REGEX_API_NAME)) {
- throw new IllegalArgumentException("接口名称只允许【字母、数字、点(.)、下划线(_)、减号(-)】,错误接口:" + name);
- }
- }
-
-
- protected String buildName(String path) {
- return RouteUtil.buildApiName(path);
- }
-
}
diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceRouteController.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceRouteController.java
new file mode 100644
index 00000000..8c92d708
--- /dev/null
+++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceRouteController.java
@@ -0,0 +1,46 @@
+package com.gitee.sop.servercommon.manager;
+
+import com.gitee.sop.servercommon.bean.ServiceApiInfo;
+import com.gitee.sop.servercommon.route.ServiceRouteInfo;
+import com.gitee.sop.servercommon.util.OpenUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * @author tanghc
+ */
+@Slf4j
+@RestController
+public class ServiceRouteController {
+
+ private static final String SECRET = "a3d9sf!1@odl90zd>fkASwq";
+
+ @Autowired
+ private RequestMappingHandlerMapping requestMappingHandlerMapping;
+
+ @Autowired
+ private Environment environment;
+
+
+ @RequestMapping("/sop/routes")
+ public ServiceRouteInfo listRoutes(HttpServletRequest request, HttpServletResponse response) {
+ if (!OpenUtil.validateSimpleSign(request, SECRET)) {
+ log.error("签名验证失败, params:{}", request.getQueryString());
+ return null;
+ }
+ String serviceId = environment.getProperty("spring.application.name");
+ ApiMetaBuilder apiMetaBuilder = new ApiMetaBuilder();
+ ServiceApiInfo serviceApiInfo = apiMetaBuilder.getServiceApiInfo(serviceId, requestMappingHandlerMapping);
+ ServiceRouteInfoBuilder serviceRouteInfoBuilder = new ServiceRouteInfoBuilder(environment);
+ return serviceRouteInfoBuilder.build(serviceApiInfo);
+ }
+
+
+}
diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceRouteInfoBuilder.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceRouteInfoBuilder.java
new file mode 100644
index 00000000..868a8756
--- /dev/null
+++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceRouteInfoBuilder.java
@@ -0,0 +1,150 @@
+package com.gitee.sop.servercommon.manager;
+
+import com.alibaba.fastjson.JSON;
+import com.gitee.sop.servercommon.bean.ServiceApiInfo;
+import com.gitee.sop.servercommon.route.GatewayPredicateDefinition;
+import com.gitee.sop.servercommon.route.GatewayRouteDefinition;
+import com.gitee.sop.servercommon.route.ServiceRouteInfo;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.core.env.Environment;
+import org.springframework.util.DigestUtils;
+import org.springframework.util.StringUtils;
+
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author tanghc
+ */
+@Slf4j
+public class ServiceRouteInfoBuilder {
+
+ /**
+ * 网关对应的LoadBalance协议
+ */
+ private static final String PROTOCOL_LOAD_BALANCE = "lb://";
+
+ private static final String PATH_SPLIT = "/";
+
+ private static final String DEFAULT_CONTEXT_PATH = "/";
+
+ /**
+ * NameVersion=alipay.story.get1.0
+ * see com.gitee.sop.gatewaycommon.routeDefinition.NameVersionRoutePredicateFactory
+ */
+ private static String QUERY_PREDICATE_DEFINITION_TPL = "NameVersion=%s";
+
+ private static ServiceApiInfo.ApiMeta FIRST_API_META = new ServiceApiInfo.ApiMeta("_first.route_", "/", "v_000");
+
+ private Environment environment;
+
+ public ServiceRouteInfoBuilder(Environment environment) {
+ this.environment = environment;
+ }
+
+ public ServiceRouteInfo build(ServiceApiInfo serviceApiInfo) {
+ return this.buildServiceGatewayInfo(serviceApiInfo);
+ }
+
+ /**
+ * 构建接口信息,符合spring cloud gateway的格式
+ *
+ * @param serviceApiInfo 服务接口信息
+ * @return 返回服务路由信息
+ */
+ protected ServiceRouteInfo buildServiceGatewayInfo(ServiceApiInfo serviceApiInfo) {
+ List apis = serviceApiInfo.getApis();
+ List routeDefinitionList = new ArrayList<>(apis.size());
+ routeDefinitionList.add(this.buildReadBodyRouteDefinition(serviceApiInfo));
+ for (ServiceApiInfo.ApiMeta apiMeta : apis) {
+ GatewayRouteDefinition gatewayRouteDefinition = this.buildGatewayRouteDefinition(serviceApiInfo, apiMeta);
+ routeDefinitionList.add(gatewayRouteDefinition);
+ }
+ ServiceRouteInfo serviceRouteInfo = new ServiceRouteInfo();
+ serviceRouteInfo.setServiceId(serviceApiInfo.getServiceId());
+ serviceRouteInfo.setRouteDefinitionList(routeDefinitionList);
+ String md5 = buildMd5(routeDefinitionList);
+ serviceRouteInfo.setMd5(md5);
+ return serviceRouteInfo;
+ }
+
+ /**
+ * 构建路由id MD5
+ *
+ * @param routeDefinitionList 路由列表
+ * @return 返回MD5
+ */
+ protected String buildMd5(List routeDefinitionList) {
+ List routeIdList = routeDefinitionList.stream()
+ .map(JSON::toJSONString)
+ .sorted()
+ .collect(Collectors.toList());
+ String md5Source = org.apache.commons.lang3.StringUtils.join(routeIdList, "");
+ return DigestUtils.md5DigestAsHex(md5Source.getBytes(StandardCharsets.UTF_8));
+ }
+
+ protected GatewayRouteDefinition buildGatewayRouteDefinition(ServiceApiInfo serviceApiInfo, ServiceApiInfo.ApiMeta apiMeta) {
+ GatewayRouteDefinition gatewayRouteDefinition = new GatewayRouteDefinition();
+ // 唯一id规则:接口名 + 版本号
+ String routeId = apiMeta.fetchNameVersion();
+ this.checkPath(routeId, "接口定义(" + routeId + ")不能有斜杠字符'/'");
+ BeanUtils.copyProperties(apiMeta, gatewayRouteDefinition);
+ gatewayRouteDefinition.setId(routeId);
+ gatewayRouteDefinition.setFilters(Collections.emptyList());
+ gatewayRouteDefinition.setPredicates(this.buildPredicates(apiMeta));
+ String uri = this.buildUri(serviceApiInfo, apiMeta);
+ String path = this.buildServletPath(serviceApiInfo, apiMeta);
+ gatewayRouteDefinition.setUri(uri);
+ gatewayRouteDefinition.setPath(path);
+ return gatewayRouteDefinition;
+ }
+
+ protected List buildPredicates(ServiceApiInfo.ApiMeta apiMeta) {
+ GatewayPredicateDefinition gatewayPredicateDefinition = new GatewayPredicateDefinition();
+ gatewayPredicateDefinition.setName("ReadBody");
+ return Arrays.asList(gatewayPredicateDefinition, this.buildNameVersionPredicateDefinition(apiMeta));
+ }
+
+ protected GatewayPredicateDefinition buildNameVersionPredicateDefinition(ServiceApiInfo.ApiMeta apiMeta) {
+ return new GatewayPredicateDefinition(String.format(QUERY_PREDICATE_DEFINITION_TPL, apiMeta.fetchNameVersion()));
+ }
+
+ /**
+ * 添加com.gitee.sop.gatewaycommon.routeDefinition.ReadBodyRoutePredicateFactory,解决form表单获取不到问题
+ *
+ * @return 返回路由定义
+ */
+ protected GatewayRouteDefinition buildReadBodyRouteDefinition(ServiceApiInfo serviceApiInfo) {
+ GatewayRouteDefinition readBodyRouteDefinition = this.buildGatewayRouteDefinition(serviceApiInfo, FIRST_API_META);
+ readBodyRouteDefinition.setOrder(Integer.MIN_VALUE);
+
+ readBodyRouteDefinition.setPredicates(this.buildPredicates(FIRST_API_META));
+
+ return readBodyRouteDefinition;
+ }
+
+ protected String buildUri(ServiceApiInfo serviceApiInfo, ServiceApiInfo.ApiMeta apiMeta) {
+ return PROTOCOL_LOAD_BALANCE + serviceApiInfo.getServiceId();
+ }
+
+ protected String buildServletPath(ServiceApiInfo serviceApiInfo, ServiceApiInfo.ApiMeta apiMeta) {
+ String contextPath = environment.getProperty("server.servlet.context-path", DEFAULT_CONTEXT_PATH);
+ String servletPath = apiMeta.getPath();
+ if (servletPath == null) {
+ servletPath = "";
+ }
+ servletPath = StringUtils.trimLeadingCharacter(servletPath, '/');
+ return contextPath + servletPath;
+ }
+
+ private void checkPath(String path, String errorMsg) {
+ if (path.contains(PATH_SPLIT)) {
+ throw new IllegalArgumentException(errorMsg);
+ }
+ }
+}
diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceZookeeperApiMetaManager.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceZookeeperApiMetaManager.java
deleted file mode 100644
index 10ff3503..00000000
--- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceZookeeperApiMetaManager.java
+++ /dev/null
@@ -1,271 +0,0 @@
-package com.gitee.sop.servercommon.manager;
-
-import com.alibaba.fastjson.JSON;
-import com.gitee.sop.servercommon.bean.ServiceApiInfo;
-import com.gitee.sop.servercommon.bean.ZookeeperTool;
-import com.gitee.sop.servercommon.exception.ZookeeperPathNotExistException;
-import com.gitee.sop.servercommon.route.GatewayPredicateDefinition;
-import com.gitee.sop.servercommon.route.GatewayRouteDefinition;
-import com.gitee.sop.servercommon.route.ServiceRouteInfo;
-import lombok.Getter;
-import lombok.Setter;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.BeanUtils;
-import org.springframework.core.env.Environment;
-import org.springframework.util.DigestUtils;
-import org.springframework.util.StringUtils;
-
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-import java.util.stream.Collectors;
-
-/**
- * 上传路由到zookeeper
- *
- * @author tanghc
- */
-@Slf4j
-@Getter
-@Setter
-public class ServiceZookeeperApiMetaManager implements ApiMetaManager {
-
- /** 网关对应的LoadBalance协议 */
- private static final String PROTOCOL_LOAD_BALANCE = "lb://";
-
- private static final String PATH_SPLIT = "/";
-
- private static final String DEFAULT_CONTEXT_PATH = "/";
-
- /**
- * NameVersion=alipay.story.get1.0
- * see com.gitee.sop.gatewaycommon.routeDefinition.NameVersionRoutePredicateFactory
- */
- private static String QUERY_PREDICATE_DEFINITION_TPL = "NameVersion=%s";
-
- private static ServiceApiInfo.ApiMeta FIRST_API_META = new ServiceApiInfo.ApiMeta("_first.route_", "/", "v_000");
-
-
- private Environment environment;
-
- private ZookeeperTool zookeeperTool;
-
- private String serviceId;
-
- public ServiceZookeeperApiMetaManager(Environment environment) {
- this.environment = environment;
- serviceId = environment.getProperty("spring.application.name");
- if (StringUtils.isEmpty(serviceId)) {
- throw new IllegalArgumentException("请在application.properties中指定spring.application.name属性");
- }
- this.zookeeperTool = new ZookeeperTool(environment);
-
- this.uploadServiceId(environment);
- }
-
- /**
- * 上传serviceId目录
- *
- * @param environment environment
- */
- protected void uploadServiceId(Environment environment) {
- try {
- this.checkZookeeperNode(serviceId, "serviceId(" + serviceId + ")不能有斜杠字符'/'");
- ServiceRouteInfo serviceRouteInfo = this.buildServiceRouteInfo();
- // 保存路径
- String savePath = serviceRouteInfo.getZookeeperPath();
- String nodeData = JSON.toJSONString(serviceRouteInfo);
- log.info("serviceId:{}, zookeeper保存路径:{}", serviceId, savePath);
- this.zookeeperTool.createPath(savePath, nodeData);
- this.zookeeperTool.createPath(serviceRouteInfo.getZookeeperTempServiceIdPath(), "");
- } catch (Exception e) {
- throw new IllegalStateException("zookeeper操作失败");
- }
- }
-
- @Override
- public void uploadApi(ServiceApiInfo serviceApiInfo) {
- try {
- ServiceRouteInfo serviceRouteInfo = this.buildServiceGatewayInfo(serviceApiInfo);
- this.uploadServiceRouteInfoToZookeeper(serviceRouteInfo);
- // 同时上传一个临时节点
- String tempPath = serviceRouteInfo.getZookeeperTempServiceIdChildPath();
- this.zookeeperTool.createOrUpdateEphemeralSequentialPath(tempPath, JSON.toJSONString(serviceRouteInfo));
- } catch (Exception e) {
- log.error("上传一个临时节点失败, serviceApiInfo:{}", serviceApiInfo, e);
- }
- }
-
- /**
- * 构建接口信息,符合spring cloud gateway的格式
- *
- * @param serviceApiInfo 服务接口信息
- * @return 返回服务路由信息
- */
- protected ServiceRouteInfo buildServiceGatewayInfo(ServiceApiInfo serviceApiInfo) {
- List apis = serviceApiInfo.getApis();
- List routeDefinitionList = new ArrayList<>(apis.size());
- routeDefinitionList.add(this.buildReadBodyRouteDefinition(serviceApiInfo));
- for (ServiceApiInfo.ApiMeta apiMeta : apis) {
- GatewayRouteDefinition gatewayRouteDefinition = this.buildGatewayRouteDefinition(serviceApiInfo, apiMeta);
- routeDefinitionList.add(gatewayRouteDefinition);
- }
- ServiceRouteInfo serviceRouteInfo = this.buildServiceRouteInfo();
- serviceRouteInfo.setRouteDefinitionList(routeDefinitionList);
- String md5 = buildMd5(routeDefinitionList);
- serviceRouteInfo.setMd5(md5);
- return serviceRouteInfo;
- }
-
- /**
- * 构建路由id MD5
- *
- * @param routeDefinitionList 路由列表
- * @return 返回MD5
- */
- protected String buildMd5(List routeDefinitionList) {
- List routeIdList = routeDefinitionList.stream()
- .map(JSON::toJSONString)
- .sorted()
- .collect(Collectors.toList());
- String md5Source = org.apache.commons.lang3.StringUtils.join(routeIdList, "");
- return DigestUtils.md5DigestAsHex(md5Source.getBytes(StandardCharsets.UTF_8));
- }
-
- protected ServiceRouteInfo buildServiceRouteInfo() {
- ServiceRouteInfo serviceRouteInfo = new ServiceRouteInfo();
- serviceRouteInfo.setServiceId(serviceId);
- String description = environment.getProperty("spring.application.description");
- serviceRouteInfo.setDescription(description);
- return serviceRouteInfo;
- }
-
- protected GatewayRouteDefinition buildGatewayRouteDefinition(ServiceApiInfo serviceApiInfo, ServiceApiInfo.ApiMeta apiMeta) {
- GatewayRouteDefinition gatewayRouteDefinition = new GatewayRouteDefinition();
- // 唯一id规则:接口名 + 版本号
- String routeId = apiMeta.fetchNameVersion();
- this.checkZookeeperNode(routeId, "接口定义(" + routeId + ")不能有斜杠字符'/'");
- BeanUtils.copyProperties(apiMeta, gatewayRouteDefinition);
- gatewayRouteDefinition.setId(routeId);
- gatewayRouteDefinition.setFilters(Collections.emptyList());
- gatewayRouteDefinition.setPredicates(this.buildPredicates(apiMeta));
- String uri = this.buildUri(serviceApiInfo, apiMeta);
- String path = this.buildServletPath(serviceApiInfo, apiMeta);
- gatewayRouteDefinition.setUri(uri);
- gatewayRouteDefinition.setPath(path);
- return gatewayRouteDefinition;
- }
-
- protected List buildPredicates(ServiceApiInfo.ApiMeta apiMeta) {
- GatewayPredicateDefinition gatewayPredicateDefinition = new GatewayPredicateDefinition();
- gatewayPredicateDefinition.setName("ReadBody");
- return Arrays.asList(gatewayPredicateDefinition, this.buildNameVersionPredicateDefinition(apiMeta));
- }
-
- protected GatewayPredicateDefinition buildNameVersionPredicateDefinition(ServiceApiInfo.ApiMeta apiMeta) {
- return new GatewayPredicateDefinition(String.format(QUERY_PREDICATE_DEFINITION_TPL, apiMeta.fetchNameVersion()));
- }
-
- /**
- * 添加com.gitee.sop.gatewaycommon.routeDefinition.ReadBodyRoutePredicateFactory,解决form表单获取不到问题
- *
- * @return 返回路由定义
- */
- protected GatewayRouteDefinition buildReadBodyRouteDefinition(ServiceApiInfo serviceApiInfo) {
- GatewayRouteDefinition readBodyRouteDefinition = this.buildGatewayRouteDefinition(serviceApiInfo, FIRST_API_META);
- readBodyRouteDefinition.setOrder(Integer.MIN_VALUE);
-
- readBodyRouteDefinition.setPredicates(this.buildPredicates(FIRST_API_META));
-
- return readBodyRouteDefinition;
- }
-
- protected String buildUri(ServiceApiInfo serviceApiInfo, ServiceApiInfo.ApiMeta apiMeta) {
- return PROTOCOL_LOAD_BALANCE + serviceApiInfo.getServiceId();
- }
-
- protected String buildServletPath(ServiceApiInfo serviceApiInfo, ServiceApiInfo.ApiMeta apiMeta) {
- String contextPath = environment.getProperty("server.servlet.context-path", DEFAULT_CONTEXT_PATH);
- String servletPath = apiMeta.getPath();
- if (servletPath == null) {
- servletPath = "";
- }
- servletPath = StringUtils.trimLeadingCharacter(servletPath, '/');
- return contextPath + servletPath;
- }
-
- /**
- * 上传接口信息到zookeeper
- *
- * @param serviceRouteInfo 路由服务信息
- */
- protected void uploadServiceRouteInfoToZookeeper(ServiceRouteInfo serviceRouteInfo) {
- String savePath = serviceRouteInfo.getZookeeperPath();
- try {
- String existServiceRouteInfoData = zookeeperTool.getData(savePath);
- ServiceRouteInfo serviceRouteInfoExist = JSON.parseObject(existServiceRouteInfoData, ServiceRouteInfo.class);
- String oldMD5 = serviceRouteInfoExist.getMd5();
- String newMD5 = serviceRouteInfo.getMd5();
- if (Objects.equals(oldMD5, newMD5)) {
- log.info("接口没有改变,无需上传路由信息");
- return;
- }
- } catch (ZookeeperPathNotExistException e) {
- log.warn("服务路径不存在,path:{}", savePath);
- }
- try {
- log.info("上传接口信息到zookeeper,path:{}, serviceId:{}, 接口数量:{}",
- savePath,
- serviceRouteInfo.getServiceId(),
- serviceRouteInfo.getRouteDefinitionList().size());
-
- String parentPath = this.uploadFolder(serviceRouteInfo);
- this.uploadRouteItems(serviceRouteInfo, parentPath);
- } catch (Exception e) {
- log.error("更新接口信息到zookeeper失败, serviceId:{}", serviceRouteInfo.getServiceId(), e);
- }
- }
-
- /**
- * 上传文件夹内容
- *
- * @param serviceRouteInfo 路由服务信息
- * @return 返回文件夹路径
- */
- protected String uploadFolder(ServiceRouteInfo serviceRouteInfo) throws Exception {
- // 保存路径
- String savePath = serviceRouteInfo.getZookeeperPath();
- String serviceRouteInfoJson = JSON.toJSONString(serviceRouteInfo);
- log.info("上传service目录到zookeeper,路径:{},内容:{}", savePath, serviceRouteInfoJson);
- this.zookeeperTool.createOrUpdateData(savePath, serviceRouteInfoJson);
- return savePath;
- }
-
- /**
- * 上传路由信息
- *
- * @param serviceRouteInfo 路由服务
- * @param parentPath 父节点
- * @throws Exception
- */
- protected void uploadRouteItems(ServiceRouteInfo serviceRouteInfo, String parentPath) throws Exception {
- List routeDefinitionList = serviceRouteInfo.getRouteDefinitionList();
- for (GatewayRouteDefinition routeDefinition : routeDefinitionList) {
- // 父目录/子目录
- String savePath = parentPath + PATH_SPLIT + routeDefinition.getId();
- String routeDefinitionJson = JSON.toJSONString(routeDefinition);
- log.info("上传路由配置到zookeeper,路径:{},路由数据:{}", savePath, routeDefinitionJson);
- this.zookeeperTool.createOrUpdateData(savePath, routeDefinitionJson);
- }
- }
-
- private void checkZookeeperNode(String path, String errorMsg) {
- if (path.contains(PATH_SPLIT)) {
- throw new IllegalArgumentException(errorMsg);
- }
- }
-
-}
diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/swagger/SwaggerValidator.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/swagger/SwaggerValidator.java
index 80667950..ac2a9e8f 100644
--- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/swagger/SwaggerValidator.java
+++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/swagger/SwaggerValidator.java
@@ -1,7 +1,6 @@
package com.gitee.sop.servercommon.swagger;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.util.DigestUtils;
+import com.gitee.sop.servercommon.util.OpenUtil;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -33,14 +32,7 @@ public class SwaggerValidator {
}
public boolean validate(HttpServletRequest request) {
- String time = request.getParameter("time");
- String sign = request.getParameter("sign");
- if (StringUtils.isAnyBlank(time, sign)) {
- return false;
- }
- String source = secret + time + secret;
- String serverSign = DigestUtils.md5DigestAsHex(source.getBytes());
- return serverSign.equals(sign);
+ return OpenUtil.validateSimpleSign(request, secret);
}
public void writeForbidden(HttpServletResponse response) throws IOException {
diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/util/OpenUtil.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/util/OpenUtil.java
index a99813cd..d4f7eb26 100644
--- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/util/OpenUtil.java
+++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/util/OpenUtil.java
@@ -6,6 +6,7 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
+import org.springframework.util.DigestUtils;
import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
@@ -75,4 +76,14 @@ public class OpenUtil {
return retMap;
}
+ public static boolean validateSimpleSign(HttpServletRequest request, String secret) {
+ String time = request.getParameter("time");
+ String sign = request.getParameter("sign");
+ if (StringUtils.isAnyBlank(time, sign)) {
+ return false;
+ }
+ String source = secret + time + secret;
+ String serverSign = DigestUtils.md5DigestAsHex(source.getBytes());
+ return serverSign.equals(sign);
+ }
}
diff --git a/sop-example/sop-story/sop-story-web/pom.xml b/sop-example/sop-story/sop-story-web/pom.xml
index f800e269..b9bf7682 100644
--- a/sop-example/sop-story/sop-story-web/pom.xml
+++ b/sop-example/sop-story/sop-story-web/pom.xml
@@ -48,6 +48,17 @@
org.springframework.cloud
spring-cloud-starter-alibaba-nacos-discovery
0.2.2.RELEASE
+
+
+ com.alibaba.nacos
+ nacos-client
+
+
+
+
+ com.alibaba.nacos
+ nacos-client
+ 1.1.0
@@ -73,6 +84,11 @@
netty-all
+
+ com.google.guava
+ guava
+ 25.1-jre
+
diff --git a/sop-gateway/pom.xml b/sop-gateway/pom.xml
index 4146a1c0..273161b7 100644
--- a/sop-gateway/pom.xml
+++ b/sop-gateway/pom.xml
@@ -65,15 +65,6 @@
runtime
-
-
-
-
diff --git a/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbEnvGrayManager.java b/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbEnvGrayManager.java
index 305ace89..fb2f5603 100644
--- a/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbEnvGrayManager.java
+++ b/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbEnvGrayManager.java
@@ -1,20 +1,23 @@
package com.gitee.sop.gateway.manager;
import com.alibaba.fastjson.JSON;
+import com.alibaba.nacos.api.config.ConfigService;
+import com.alibaba.nacos.api.config.listener.AbstractListener;
import com.gitee.fastmybatis.core.query.Query;
import com.gitee.sop.gateway.entity.ConfigGray;
import com.gitee.sop.gateway.entity.ConfigGrayInstance;
import com.gitee.sop.gateway.mapper.ConfigGrayInstanceMapper;
import com.gitee.sop.gateway.mapper.ConfigGrayMapper;
import com.gitee.sop.gatewaycommon.bean.ChannelMsg;
+import com.gitee.sop.gatewaycommon.bean.NacosConfigs;
import com.gitee.sop.gatewaycommon.bean.ServiceGrayDefinition;
import com.gitee.sop.gatewaycommon.manager.DefaultEnvGrayManager;
-import com.gitee.sop.gatewaycommon.manager.ZookeeperContext;
import com.gitee.sop.gatewaycommon.zuul.loadbalancer.ServiceGrayConfig;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.alibaba.nacos.NacosConfigProperties;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
@@ -50,6 +53,9 @@ public class DbEnvGrayManager extends DefaultEnvGrayManager {
@Autowired
private ConfigGrayInstanceMapper configGrayInstanceMapper;
+ @Autowired
+ private NacosConfigProperties nacosConfigProperties;
+
@Override
public void load() {
@@ -98,7 +104,7 @@ public class DbEnvGrayManager extends DefaultEnvGrayManager {
@PostConstruct
protected void after() throws Exception {
- ZookeeperContext.setEnvironment(environment);
+ /*ZookeeperContext.setEnvironment(environment);
String isvChannelPath = ZookeeperContext.getServiceGrayChannelPath();
ZookeeperContext.listenPath(isvChannelPath, nodeCache -> {
String nodeData = new String(nodeCache.getCurrentData().getData());
@@ -120,6 +126,31 @@ public class DbEnvGrayManager extends DefaultEnvGrayManager {
default:
}
+ });*/
+
+ // nacos
+ ConfigService configService = nacosConfigProperties.configServiceInstance();
+ configService.addListener(NacosConfigs.DATA_ID_GRAY, NacosConfigs.GROUP_CHANNEL, new AbstractListener() {
+ @Override
+ public void receiveConfigInfo(String configInfo) {
+ ChannelMsg channelMsg = JSON.parseObject(configInfo, ChannelMsg.class);
+ String data = channelMsg.getData();
+ ServiceGrayDefinition userKeyDefinition = JSON.parseObject(data, ServiceGrayDefinition.class);
+ String serviceId = userKeyDefinition.getServiceId();
+ switch (channelMsg.getOperation()) {
+ case "set":
+ ConfigGray configGray = configGrayMapper.getByColumn("service_id", serviceId);
+ setServiceGrayConfig(configGray);
+ break;
+ case "open":
+ openGray(userKeyDefinition.getInstanceId(), serviceId);
+ break;
+ case "close":
+ closeGray(userKeyDefinition.getInstanceId());
+ break;
+ default:
+ }
+ }
});
}
diff --git a/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbIPBlacklistManager.java b/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbIPBlacklistManager.java
index 7db0eada..7ab89cda 100644
--- a/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbIPBlacklistManager.java
+++ b/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbIPBlacklistManager.java
@@ -1,13 +1,16 @@
package com.gitee.sop.gateway.manager;
import com.alibaba.fastjson.JSON;
+import com.alibaba.nacos.api.config.ConfigService;
+import com.alibaba.nacos.api.config.listener.AbstractListener;
import com.gitee.sop.gateway.mapper.IPBlacklistMapper;
import com.gitee.sop.gatewaycommon.bean.ChannelMsg;
+import com.gitee.sop.gatewaycommon.bean.NacosConfigs;
import com.gitee.sop.gatewaycommon.manager.DefaultIPBlacklistManager;
-import com.gitee.sop.gatewaycommon.manager.ZookeeperContext;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.alibaba.nacos.NacosConfigProperties;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
@@ -29,6 +32,9 @@ public class DbIPBlacklistManager extends DefaultIPBlacklistManager {
@Autowired
Environment environment;
+ @Autowired
+ private NacosConfigProperties nacosConfigProperties;
+
@Override
public void load() {
List ipList = ipBlacklistMapper.listAllIP();
@@ -39,7 +45,7 @@ public class DbIPBlacklistManager extends DefaultIPBlacklistManager {
@PostConstruct
protected void after() throws Exception {
- ZookeeperContext.setEnvironment(environment);
+ /*ZookeeperContext.setEnvironment(environment);
String path = ZookeeperContext.getIpBlacklistChannelPath();
ZookeeperContext.listenPath(path, nodeCache -> {
String nodeData = new String(nodeCache.getCurrentData().getData());
@@ -57,6 +63,27 @@ public class DbIPBlacklistManager extends DefaultIPBlacklistManager {
break;
default:
}
+ });*/
+ // nacos
+ ConfigService configService = nacosConfigProperties.configServiceInstance();
+ configService.addListener(NacosConfigs.DATA_ID_IP_BLACKLIST, NacosConfigs.GROUP_CHANNEL, new AbstractListener() {
+ @Override
+ public void receiveConfigInfo(String configInfo) {
+ ChannelMsg channelMsg = JSON.parseObject(configInfo, ChannelMsg.class);
+ final IPDto ipDto = JSON.parseObject(channelMsg.getData(), IPDto.class);
+ String ip = ipDto.getIp();
+ switch (channelMsg.getOperation()) {
+ case "add":
+ log.info("添加IP黑名单,ip:{}", ip);
+ add(ip);
+ break;
+ case "delete":
+ log.info("移除IP黑名单,ip:{}", ip);
+ remove(ip);
+ break;
+ default:
+ }
+ }
});
}
diff --git a/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbIsvManager.java b/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbIsvManager.java
index 6ece0b03..9e361eeb 100644
--- a/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbIsvManager.java
+++ b/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbIsvManager.java
@@ -1,16 +1,19 @@
package com.gitee.sop.gateway.manager;
import com.alibaba.fastjson.JSON;
+import com.alibaba.nacos.api.config.ConfigService;
+import com.alibaba.nacos.api.config.listener.AbstractListener;
import com.gitee.sop.gateway.entity.IsvDetailDTO;
import com.gitee.sop.gateway.mapper.IsvInfoMapper;
import com.gitee.sop.gatewaycommon.bean.ApiConfig;
import com.gitee.sop.gatewaycommon.bean.ChannelMsg;
import com.gitee.sop.gatewaycommon.bean.IsvDefinition;
-import com.gitee.sop.gatewaycommon.manager.ZookeeperContext;
+import com.gitee.sop.gatewaycommon.bean.NacosConfigs;
import com.gitee.sop.gatewaycommon.secret.CacheIsvManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.alibaba.nacos.NacosConfigProperties;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
@@ -30,6 +33,8 @@ public class DbIsvManager extends CacheIsvManager {
@Autowired
Environment environment;
+ @Autowired
+ private NacosConfigProperties nacosConfigProperties;
@Override
public void load() {
@@ -45,7 +50,7 @@ public class DbIsvManager extends CacheIsvManager {
@PostConstruct
protected void after() throws Exception {
ApiConfig.getInstance().setIsvManager(this);
- ZookeeperContext.setEnvironment(environment);
+ /*ZookeeperContext.setEnvironment(environment);
String isvChannelPath = ZookeeperContext.getIsvInfoChannelPath();
ZookeeperContext.listenPath(isvChannelPath, nodeCache -> {
String nodeData = new String(nodeCache.getCurrentData().getData());
@@ -63,6 +68,27 @@ public class DbIsvManager extends CacheIsvManager {
default:
}
+ });*/
+
+ ConfigService configService = nacosConfigProperties.configServiceInstance();
+ configService.addListener(NacosConfigs.DATA_ID_ISV, NacosConfigs.GROUP_CHANNEL, new AbstractListener() {
+ @Override
+ public void receiveConfigInfo(String configInfo) {
+ ChannelMsg channelMsg = JSON.parseObject(configInfo, ChannelMsg.class);
+ final IsvDefinition isvDefinition = JSON.parseObject(channelMsg.getData(), IsvDefinition.class);
+ switch (channelMsg.getOperation()) {
+ case "update":
+ log.info("更新ISV信息,isvDefinition:{}", isvDefinition);
+ update(isvDefinition);
+ break;
+ case "remove":
+ log.info("删除ISV,isvDefinition:{}", isvDefinition);
+ remove(isvDefinition.getAppKey());
+ break;
+ default:
+
+ }
+ }
});
}
diff --git a/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbIsvRoutePermissionManager.java b/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbIsvRoutePermissionManager.java
index 0715703a..8ea658f8 100644
--- a/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbIsvRoutePermissionManager.java
+++ b/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbIsvRoutePermissionManager.java
@@ -1,6 +1,8 @@
package com.gitee.sop.gateway.manager;
import com.alibaba.fastjson.JSON;
+import com.alibaba.nacos.api.config.ConfigService;
+import com.alibaba.nacos.api.config.listener.AbstractListener;
import com.gitee.fastmybatis.core.query.Query;
import com.gitee.sop.gateway.entity.IsvInfo;
import com.gitee.sop.gateway.entity.PermIsvRole;
@@ -10,12 +12,13 @@ import com.gitee.sop.gateway.mapper.PermIsvRoleMapper;
import com.gitee.sop.gateway.mapper.PermRolePermissionMapper;
import com.gitee.sop.gatewaycommon.bean.ChannelMsg;
import com.gitee.sop.gatewaycommon.bean.IsvRoutePermission;
+import com.gitee.sop.gatewaycommon.bean.NacosConfigs;
import com.gitee.sop.gatewaycommon.manager.DefaultIsvRoutePermissionManager;
-import com.gitee.sop.gatewaycommon.manager.ZookeeperContext;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.alibaba.nacos.NacosConfigProperties;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
@@ -51,6 +54,9 @@ public class DbIsvRoutePermissionManager extends DefaultIsvRoutePermissionManage
@Autowired
IsvInfoMapper isvInfoMapper;
+ @Autowired
+ private NacosConfigProperties nacosConfigProperties;
+
@Override
public void load() {
// key: appKey, value: roleCodeList
@@ -121,7 +127,7 @@ public class DbIsvRoutePermissionManager extends DefaultIsvRoutePermissionManage
@PostConstruct
protected void after() throws Exception {
- ZookeeperContext.setEnvironment(environment);
+ /*ZookeeperContext.setEnvironment(environment);
String isvChannelPath = ZookeeperContext.getIsvRoutePermissionChannelPath();
ZookeeperContext.listenPath(isvChannelPath, nodeCache -> {
String nodeData = new String(nodeCache.getCurrentData().getData());
@@ -155,6 +161,36 @@ public class DbIsvRoutePermissionManager extends DefaultIsvRoutePermissionManage
default:
}
+ });*/
+
+ ConfigService configService = nacosConfigProperties.configServiceInstance();
+ configService.addListener(NacosConfigs.DATA_ID_ROUTE_PERMISSION, NacosConfigs.GROUP_CHANNEL, new AbstractListener() {
+ @Override
+ public void receiveConfigInfo(String configInfo) {
+ ChannelMsg channelMsg = JSON.parseObject(configInfo, ChannelMsg.class);
+ final IsvRoutePermission isvRoutePermission = JSON.parseObject(channelMsg.getData(), IsvRoutePermission.class);
+ switch (channelMsg.getOperation()) {
+ case "reload":
+ log.info("重新加载路由权限信息,isvRoutePermission:{}", isvRoutePermission);
+ String listenPath = isvRoutePermission.getListenPath();
+ try {
+ load();
+ } catch (Exception e) {
+ log.error("重新加载路由权限失败, channelMsg:{}", channelMsg, e);
+ }
+ break;
+ case "update":
+ log.info("更新ISV路由权限信息,isvRoutePermission:{}", isvRoutePermission);
+ update(isvRoutePermission);
+ break;
+ case "remove":
+ log.info("删除ISV路由权限信息,isvRoutePermission:{}", isvRoutePermission);
+ remove(isvRoutePermission.getAppKey());
+ break;
+ default:
+
+ }
+ }
});
}
}
diff --git a/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbLimitConfigManager.java b/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbLimitConfigManager.java
index 0f150334..9aab7fda 100644
--- a/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbLimitConfigManager.java
+++ b/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbLimitConfigManager.java
@@ -1,15 +1,18 @@
package com.gitee.sop.gateway.manager;
import com.alibaba.fastjson.JSON;
+import com.alibaba.nacos.api.config.ConfigService;
+import com.alibaba.nacos.api.config.listener.AbstractListener;
import com.gitee.fastmybatis.core.query.Query;
import com.gitee.sop.gateway.mapper.ConfigLimitMapper;
import com.gitee.sop.gatewaycommon.bean.ChannelMsg;
import com.gitee.sop.gatewaycommon.bean.ConfigLimitDto;
+import com.gitee.sop.gatewaycommon.bean.NacosConfigs;
import com.gitee.sop.gatewaycommon.manager.DefaultLimitConfigManager;
-import com.gitee.sop.gatewaycommon.manager.ZookeeperContext;
import com.gitee.sop.gatewaycommon.util.MyBeanUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.alibaba.nacos.NacosConfigProperties;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
@@ -29,6 +32,9 @@ public class DbLimitConfigManager extends DefaultLimitConfigManager {
@Autowired
Environment environment;
+ @Autowired
+ private NacosConfigProperties nacosConfigProperties;
+
@Override
public void load() {
Query query = new Query();
@@ -47,7 +53,7 @@ public class DbLimitConfigManager extends DefaultLimitConfigManager {
@PostConstruct
protected void after() throws Exception {
- ZookeeperContext.setEnvironment(environment);
+ /*ZookeeperContext.setEnvironment(environment);
String path = ZookeeperContext.getLimitConfigChannelPath();
ZookeeperContext.listenPath(path, nodeCache -> {
String nodeData = new String(nodeCache.getCurrentData().getData());
@@ -64,6 +70,26 @@ public class DbLimitConfigManager extends DefaultLimitConfigManager {
break;
default:
}
+ });*/
+
+ ConfigService configService = nacosConfigProperties.configServiceInstance();
+ configService.addListener(NacosConfigs.DATA_ID_LIMIT_CONFIG, NacosConfigs.GROUP_CHANNEL, new AbstractListener() {
+ @Override
+ public void receiveConfigInfo(String configInfo) {
+ ChannelMsg channelMsg = JSON.parseObject(configInfo, ChannelMsg.class);
+ final ConfigLimitDto configLimitDto = JSON.parseObject(channelMsg.getData(), ConfigLimitDto.class);
+ switch (channelMsg.getOperation()) {
+ case "reload":
+ log.info("重新加载限流配置信息,configLimitDto:{}", configLimitDto);
+ load();
+ break;
+ case "update":
+ log.info("更新限流配置信息,configLimitDto:{}", configLimitDto);
+ update(configLimitDto);
+ break;
+ default:
+ }
+ }
});
}
diff --git a/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbRouteConfigManager.java b/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbRouteConfigManager.java
index ef7125f5..4b92cdcd 100644
--- a/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbRouteConfigManager.java
+++ b/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbRouteConfigManager.java
@@ -1,18 +1,21 @@
package com.gitee.sop.gateway.manager;
import com.alibaba.fastjson.JSON;
+import com.alibaba.nacos.api.config.ConfigService;
+import com.alibaba.nacos.api.config.listener.AbstractListener;
import com.gitee.fastmybatis.core.query.Query;
import com.gitee.sop.gateway.mapper.ConfigRouteBaseMapper;
import com.gitee.sop.gateway.mapper.ConfigRouteLimitMapper;
-import com.gitee.sop.gatewaycommon.bean.BaseRouteDefinition;
import com.gitee.sop.gatewaycommon.bean.ChannelMsg;
+import com.gitee.sop.gatewaycommon.bean.GatewayRouteDefinition;
+import com.gitee.sop.gatewaycommon.bean.NacosConfigs;
import com.gitee.sop.gatewaycommon.bean.RouteConfig;
import com.gitee.sop.gatewaycommon.bean.TargetRoute;
import com.gitee.sop.gatewaycommon.manager.DefaultRouteConfigManager;
import com.gitee.sop.gatewaycommon.manager.RouteRepositoryContext;
-import com.gitee.sop.gatewaycommon.manager.ZookeeperContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.alibaba.nacos.NacosConfigProperties;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
@@ -35,6 +38,9 @@ public class DbRouteConfigManager extends DefaultRouteConfigManager {
@Autowired
Environment environment;
+ @Autowired
+ private NacosConfigProperties nacosConfigProperties;
+
@Override
public void load() {
loadAllRoute();
@@ -52,12 +58,12 @@ public class DbRouteConfigManager extends DefaultRouteConfigManager {
Collection extends TargetRoute> targetRoutes = RouteRepositoryContext.getRouteRepository().getAll();
targetRoutes.stream()
.forEach(targetRoute -> {
- BaseRouteDefinition routeDefinition = targetRoute.getRouteDefinition();
+ GatewayRouteDefinition routeDefinition = targetRoute.getRouteDefinition();
initRouteConfig(routeDefinition);
});
}
- protected void initRouteConfig(BaseRouteDefinition routeDefinition) {
+ protected void initRouteConfig(GatewayRouteDefinition routeDefinition) {
String routeId = routeDefinition.getId();
RouteConfig routeConfig = newRouteConfig();
routeConfig.setRouteId(routeId);
@@ -71,7 +77,7 @@ public class DbRouteConfigManager extends DefaultRouteConfigManager {
@PostConstruct
protected void after() throws Exception {
- ZookeeperContext.setEnvironment(environment);
+ /*ZookeeperContext.setEnvironment(environment);
String path = ZookeeperContext.getRouteConfigChannelPath();
ZookeeperContext.listenPath(path, nodeCache -> {
String nodeData = new String(nodeCache.getCurrentData().getData());
@@ -88,6 +94,26 @@ public class DbRouteConfigManager extends DefaultRouteConfigManager {
break;
default:
}
+ });*/
+
+ ConfigService configService = nacosConfigProperties.configServiceInstance();
+ configService.addListener(NacosConfigs.DATA_ID_ROUTE_CONFIG, NacosConfigs.GROUP_CHANNEL, new AbstractListener() {
+ @Override
+ public void receiveConfigInfo(String configInfo) {
+ ChannelMsg channelMsg = JSON.parseObject(configInfo, ChannelMsg.class);
+ final RouteConfig routeConfig = JSON.parseObject(channelMsg.getData(), RouteConfig.class);
+ switch (channelMsg.getOperation()) {
+ case "reload":
+ log.info("重新加载路由配置信息,routeConfigDto:{}", routeConfig);
+ load();
+ break;
+ case "update":
+ log.info("更新路由配置信息,routeConfigDto:{}", routeConfig);
+ update(routeConfig);
+ break;
+ default:
+ }
+ }
});
}
}
diff --git a/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/ManagerInitializer.java b/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/ManagerInitializer.java
deleted file mode 100644
index 9f260f1b..00000000
--- a/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/ManagerInitializer.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.gitee.sop.gateway.manager;
-
-import com.gitee.sop.gatewaycommon.bean.ApiConfig;
-
-/**
- * @author tanghc
- */
-public class ManagerInitializer {
-
- public ManagerInitializer() {
- ApiConfig apiConfig = ApiConfig.getInstance();
- apiConfig.setIsvManager(new DbIsvManager());
- apiConfig.setIsvRoutePermissionManager(new DbIsvRoutePermissionManager());
- apiConfig.setRouteConfigManager(new DbRouteConfigManager());
- apiConfig.setLimitConfigManager(new DbLimitConfigManager());
- apiConfig.setIpBlacklistManager(new DbIPBlacklistManager());
- apiConfig.setUserKeyManager(new DbEnvGrayManager());
- }
-}
diff --git a/sop-gateway/src/main/resources/application-dev.properties b/sop-gateway/src/main/resources/application-dev.properties
index 297addd1..0e80a3dd 100644
--- a/sop-gateway/src/main/resources/application-dev.properties
+++ b/sop-gateway/src/main/resources/application-dev.properties
@@ -37,7 +37,7 @@ ribbon.ReadTimeout=2000
# 请谨慎设置,因为post请求大多都是写入请求,如果要支持重试,确保服务的幂等性
ribbon.OkToRetryOnAllOperations=false
-# nacos注册中心配置
+# nacos cloud配置
spring.cloud.nacos.discovery.server-addr=${nacos.url}
# zookeeper配置
diff --git a/sop-gateway/src/main/resources/bootstrap.properties b/sop-gateway/src/main/resources/bootstrap.properties
new file mode 100644
index 00000000..9af67138
--- /dev/null
+++ b/sop-gateway/src/main/resources/bootstrap.properties
@@ -0,0 +1,3 @@
+spring.application.name=api-gateway
+# nacos的config需要放在bootstrap.properties中
+spring.cloud.nacos.config.server-addr=127.0.0.1:8848
\ No newline at end of file
diff --git a/sop-gateway/src/test/java/com/gitee/sop/gateway/CuratorTest.java b/sop-gateway/src/test/java/com/gitee/sop/gateway/CuratorTest.java
deleted file mode 100644
index 91ae48b7..00000000
--- a/sop-gateway/src/test/java/com/gitee/sop/gateway/CuratorTest.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.gitee.sop.gateway;
-
-import com.gitee.sop.gatewaycommon.bean.SopConstants;
-import junit.framework.TestCase;
-import org.apache.curator.framework.CuratorFramework;
-import org.apache.curator.framework.CuratorFrameworkFactory;
-import org.apache.curator.retry.ExponentialBackoffRetry;
-
-/**
- * @author tanghc
- */
-public class CuratorTest extends TestCase {
-
- private String zookeeperServerAddr = "localhost:2181";
-
- /**
- * 递归删除节点,只能在测试环境用。
- *
- * @throws Exception
- */
- public void testDel() throws Exception {
- CuratorFramework client = CuratorFrameworkFactory.builder()
- .connectString(zookeeperServerAddr)
- .retryPolicy(new ExponentialBackoffRetry(1000, 3))
- .build();
-
- client.start();
-
- try {
- client.delete().deletingChildrenIfNeeded().forPath(SopConstants.SOP_SERVICE_ROUTE_PATH);
- } catch (Exception e) {
- }
- }
-
- /**
- * 删除临时节点
- */
- public void testDelTemp() {
- String tempRoot = "/com.gitee.sop.service.tmp";
- CuratorFramework client = CuratorFrameworkFactory.builder()
- .connectString(zookeeperServerAddr)
- .retryPolicy(new ExponentialBackoffRetry(1000, 3))
- .build();
-
- client.start();
-
- try {
- client.delete().deletingChildrenIfNeeded().forPath(tempRoot);
- } catch (Exception e) {
- }
- }
-}
diff --git a/sop-website/website-server/pom.xml b/sop-website/website-server/pom.xml
index 015d1e65..ddeb9407 100644
--- a/sop-website/website-server/pom.xml
+++ b/sop-website/website-server/pom.xml
@@ -12,20 +12,17 @@
website-server
1.0.0-SNAPSHOT
website-server
- Demo project for Spring Boot
+ website-server
1.8
- 3.4.12
- 4.0.1
-
- com.gitee.sop
- sop-registry-api
- 1.15.2-SNAPSHOT
+ org.springframework.cloud
+ spring-cloud-alibaba-nacos-discovery
+ 0.9.0.RELEASE
@@ -33,38 +30,6 @@
spring-boot-starter-web
-
-
- org.apache.curator
- curator-recipes
- ${curator-recipes.version}
-
-
- org.apache.zookeeper
- zookeeper
-
-
-
-
- org.apache.zookeeper
- zookeeper
- ${zookeeper.version}
-
-
- org.slf4j
- slf4j-log4j12
-
-
-
-
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
commons-lang
commons-lang
@@ -77,12 +42,7 @@
3.14.0
compile
-
- org.projectlombok
- lombok
- 1.18.4
- provided
-
+
com.alibaba
fastjson
@@ -94,6 +54,19 @@
httpclient
4.5.6
+
+
+ org.projectlombok
+ lombok
+ 1.18.4
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
diff --git a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/bean/HttpTool.java b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/bean/HttpTool.java
new file mode 100644
index 00000000..07362f53
--- /dev/null
+++ b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/bean/HttpTool.java
@@ -0,0 +1,381 @@
+package com.gitee.sop.websiteserver.bean;
+
+import lombok.Data;
+import lombok.Getter;
+import lombok.Setter;
+import okhttp3.Cookie;
+import okhttp3.CookieJar;
+import okhttp3.FormBody;
+import okhttp3.HttpUrl;
+import okhttp3.MediaType;
+import okhttp3.MultipartBody;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+import okhttp3.Response;
+import org.apache.commons.codec.digest.DigestUtils;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * http请求工具,基于OKHTTP3
+ * @author tanghc
+ */
+public class HttpTool {
+ private static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8");
+
+ private Map> cookieStore = new HashMap>();
+
+ private OkHttpClient httpClient;
+
+ public HttpTool() {
+ this(new HttpToolConfig());
+ }
+
+ public HttpTool(HttpToolConfig httpToolConfig) {
+ this.initHttpClient(httpToolConfig);
+ }
+
+ protected void initHttpClient(HttpToolConfig httpToolConfig) {
+ httpClient = new OkHttpClient.Builder()
+ .connectTimeout(httpToolConfig.connectTimeoutSeconds, TimeUnit.SECONDS) // 设置链接超时时间,默认10秒
+ .readTimeout(httpToolConfig.readTimeoutSeconds, TimeUnit.SECONDS)
+ .writeTimeout(httpToolConfig.writeTimeoutSeconds, TimeUnit.SECONDS)
+ .cookieJar(new CookieJar() {
+ public void saveFromResponse(HttpUrl httpUrl, List list) {
+ cookieStore.put(httpUrl.host(), list);
+ }
+
+ public List loadForRequest(HttpUrl httpUrl) {
+ List cookies = cookieStore.get(httpUrl.host());
+ return cookies != null ? cookies : new ArrayList();
+ }
+ }).build();
+ }
+
+ @Data
+ public static class HttpToolConfig {
+ /**
+ * 请求超时时间
+ */
+ private int connectTimeoutSeconds = 10;
+ /**
+ * http读取超时时间
+ */
+ private int readTimeoutSeconds = 10;
+ /**
+ * http写超时时间
+ */
+ private int writeTimeoutSeconds = 10;
+ }
+
+ /**
+ * get请求
+ *
+ * @param url
+ * @param header
+ * @return
+ * @throws IOException
+ */
+ public String get(String url, Map header) throws IOException {
+ Request.Builder builder = new Request.Builder().url(url).get();
+ // 添加header
+ addHeader(builder, header);
+
+ Request request = builder.build();
+ Response response = httpClient.newCall(request).execute();
+ return response.body().string();
+ }
+
+ /**
+ * 提交表单
+ *
+ * @param url url
+ * @param form 参数
+ * @param header header
+ * @param method 请求方式,post,get等
+ * @return
+ * @throws IOException
+ */
+ public String request(String url, Map form, Map header, HTTPMethod method) throws IOException {
+ Request.Builder requestBuilder = buildRequestBuilder(url, form, method);
+ // 添加header
+ addHeader(requestBuilder, header);
+
+ Request request = requestBuilder.build();
+ Response response = httpClient
+ .newCall(request)
+ .execute();
+ try {
+ return response.body().string();
+ } finally {
+ response.close();
+ }
+ }
+
+ /**
+ * 请求json数据,contentType=application/json
+ * @param url 请求路径
+ * @param json json数据
+ * @param header header
+ * @return 返回响应结果
+ * @throws IOException
+ */
+ public String requestJson(String url, String json, Map header) throws IOException {
+ RequestBody body = RequestBody.create(MEDIA_TYPE_JSON, json);
+ Request.Builder requestBuilder = new Request.Builder()
+ .url(url)
+ .post(body);
+ // 添加header
+ addHeader(requestBuilder, header);
+
+ Request request = requestBuilder.build();
+ Response response = httpClient
+ .newCall(request)
+ .execute();
+ try {
+ return response.body().string();
+ } finally {
+ response.close();
+ }
+ }
+
+ public static Request.Builder buildRequestBuilder(String url, Map form, HTTPMethod method) {
+ switch (method) {
+ case GET:
+ return new Request.Builder()
+ .url(buildHttpUrl(url, form))
+ .get();
+ case HEAD:
+ return new Request.Builder()
+ .url(buildHttpUrl(url, form))
+ .head();
+ case PUT:
+ return new Request.Builder()
+ .url(url)
+ .put(buildFormBody(form));
+ case DELETE:
+ return new Request.Builder()
+ .url(url)
+ .delete(buildFormBody(form));
+ default:
+ return new Request.Builder()
+ .url(url)
+ .post(buildFormBody(form));
+ }
+ }
+
+ public static HttpUrl buildHttpUrl(String url, Map form) {
+ HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();
+ for (Map.Entry entry : form.entrySet()) {
+ urlBuilder.addQueryParameter(entry.getKey(), String.valueOf(entry.getValue()));
+ }
+ return urlBuilder.build();
+ }
+
+ public static FormBody buildFormBody(Map form) {
+ FormBody.Builder paramBuilder = new FormBody.Builder(StandardCharsets.UTF_8);
+ for (Map.Entry entry : form.entrySet()) {
+ paramBuilder.add(entry.getKey(), String.valueOf(entry.getValue()));
+ }
+ return paramBuilder.build();
+ }
+
+ /**
+ * 提交表单,并且上传文件
+ *
+ * @param url
+ * @param form
+ * @param header
+ * @param files
+ * @return
+ * @throws IOException
+ */
+ public String requestFile(String url, Map form, Map header, List files)
+ throws IOException {
+ // 创建MultipartBody.Builder,用于添加请求的数据
+ MultipartBody.Builder bodyBuilder = new MultipartBody.Builder();
+ bodyBuilder.setType(MultipartBody.FORM);
+
+ for (UploadFile uploadFile : files) {
+ bodyBuilder.addFormDataPart(uploadFile.getName(), // 请求的名字
+ uploadFile.getFileName(), // 文件的文字,服务器端用来解析的
+ RequestBody.create(null, uploadFile.getFileData()) // 创建RequestBody,把上传的文件放入
+ );
+ }
+
+ Set> entrySet = form.entrySet();
+ for (Map.Entry entry : entrySet) {
+ bodyBuilder.addFormDataPart(entry.getKey(), entry.getValue());
+ }
+
+ RequestBody requestBody = bodyBuilder.build();
+
+ Request.Builder builder = new Request.Builder().url(url).post(requestBody);
+
+ // 添加header
+ addHeader(builder, header);
+
+ Request request = builder.build();
+ Response response = httpClient.newCall(request).execute();
+ try {
+ return response.body().string();
+ } finally {
+ response.close();
+ }
+ }
+
+ private void addHeader(Request.Builder builder, Map header) {
+ if (header != null) {
+ Set> entrySet = header.entrySet();
+ for (Map.Entry entry : entrySet) {
+ builder.addHeader(entry.getKey(), String.valueOf(entry.getValue()));
+ }
+ }
+ }
+
+ public void setCookieStore(Map> cookieStore) {
+ this.cookieStore = cookieStore;
+ }
+
+ public void setHttpClient(OkHttpClient httpClient) {
+ this.httpClient = httpClient;
+ }
+
+ public enum HTTPMethod {
+ GET,
+ POST,
+ PUT,
+ HEAD,
+ DELETE;
+
+ private HTTPMethod() {
+ }
+
+ public String value() {
+ return this.name();
+ }
+
+ public static HTTPMethod fromValue(String v) {
+ return valueOf(v.toUpperCase());
+ }
+ }
+
+ /**
+ * 文件上传类
+ * @author tanghc
+ */
+ @Getter
+ @Setter
+ public static class UploadFile implements Serializable {
+ private static final long serialVersionUID = -1100614660944996398L;
+
+ /**
+ * @param name 表单名称,不能重复
+ * @param file 文件
+ * @throws IOException
+ */
+ public UploadFile(String name, File file) throws IOException {
+ this(name, file.getName(), FileUtil.toBytes(file));
+ }
+
+ /**
+ * @param name 表单名称,不能重复
+ * @param fileName 文件名
+ * @param input 文件流
+ * @throws IOException
+ */
+ public UploadFile(String name, String fileName, InputStream input) throws IOException {
+ this(name, fileName, FileUtil.toBytes(input));
+ }
+
+ /**
+ * @param name 表单名称,不能重复
+ * @param fileName 文件名
+ * @param fileData 文件数据
+ */
+ public UploadFile(String name, String fileName, byte[] fileData) {
+ super();
+ this.name = name;
+ this.fileName = fileName;
+ this.fileData = fileData;
+ this.md5 = DigestUtils.md5Hex(fileData);
+ }
+
+ private String name;
+ private String fileName;
+ private byte[] fileData;
+ private String md5;
+
+ }
+
+ public static class FileUtil {
+
+ /**
+ * The default buffer size to use.
+ */
+ private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
+ private static final int EOF = -1;
+
+ /**
+ * 将文件流转换成byte[]
+ * @param input
+ * @return
+ * @throws IOException
+ */
+ public static byte[] toBytes(InputStream input) throws IOException {
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ int n = 0;
+ byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
+
+ while (EOF != (n = input.read(buffer))) {
+ output.write(buffer, 0, n);
+ }
+ return output.toByteArray();
+ }
+
+ /**
+ * 将文件转换成数据流
+ * @param file 文件
+ * @return 返回数据流
+ * @throws IOException
+ */
+ public static byte[] toBytes(File file) throws IOException {
+ if (file.exists()) {
+ if (file.isDirectory()) {
+ throw new IOException("File '" + file + "' exists but is a directory");
+ }
+ if (file.canRead() == false) {
+ throw new IOException("File '" + file + "' cannot be read");
+ }
+ } else {
+ throw new FileNotFoundException("File '" + file + "' does not exist");
+ }
+ InputStream input = null;
+ try {
+ input = new FileInputStream(file);
+ return toBytes(input);
+ } finally {
+ try {
+ if (input != null) {
+ input.close();
+ }
+ } catch (IOException ioe) {
+ }
+ }
+ }
+ }
+}
diff --git a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/bean/ZookeeperContext.java b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/bean/ZookeeperContext.java
deleted file mode 100644
index e2cd6a85..00000000
--- a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/bean/ZookeeperContext.java
+++ /dev/null
@@ -1,179 +0,0 @@
-package com.gitee.sop.websiteserver.bean;
-
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.lang.math.NumberUtils;
-import org.apache.curator.framework.CuratorFramework;
-import org.apache.curator.framework.CuratorFrameworkFactory;
-import org.apache.curator.framework.recipes.cache.ChildData;
-import org.apache.curator.framework.recipes.cache.PathChildrenCache;
-import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;
-import org.apache.curator.framework.recipes.cache.TreeCache;
-import org.apache.curator.framework.recipes.cache.TreeCacheListener;
-import org.apache.curator.retry.ExponentialBackoffRetry;
-import org.springframework.core.env.Environment;
-import org.springframework.util.Assert;
-import org.springframework.util.CollectionUtils;
-
-import java.util.List;
-import java.util.function.Consumer;
-
-/**
- * @author tanghc
- */
-@Slf4j
-public class ZookeeperContext {
-
- private static CuratorFramework client;
-
- public static void setEnvironment(Environment environment) {
- Assert.notNull(environment, "environment不能为null");
- initZookeeperClient(environment);
- }
-
- public synchronized static void initZookeeperClient(Environment environment) {
- if (client != null) {
- return;
- }
- String zookeeperServerAddr = environment.getProperty("spring.cloud.zookeeper.connect-string");
- if (StringUtils.isBlank(zookeeperServerAddr)) {
- throw new RuntimeException("未指定spring.cloud.zookeeper.connect-string参数");
- }
- String baseSleepTimeMs = environment.getProperty("spring.cloud.zookeeper.baseSleepTimeMs");
- String maxRetries = environment.getProperty("spring.cloud.zookeeper.maxRetries");
- log.info("初始化zookeeper客户端,zookeeperServerAddr:{}, baseSleepTimeMs:{}, maxRetries:{}",
- zookeeperServerAddr, baseSleepTimeMs, maxRetries);
- CuratorFramework client = CuratorFrameworkFactory.builder()
- .connectString(zookeeperServerAddr)
- .retryPolicy(new ExponentialBackoffRetry(NumberUtils.toInt(baseSleepTimeMs, 3000), NumberUtils.toInt(maxRetries, 3)))
- .build();
-
- client.start();
-
- setClient(client);
- }
-
- public static String getRouteRootPath() {
- return WebsiteConstants.SOP_SERVICE_ROUTE_PATH;
- }
-
- public static String getServiceTempRootPath() {
- return WebsiteConstants.SOP_SERVICE_TEMP_PATH;
- }
-
- public static CuratorFramework getClient() {
- return client;
- }
-
- public static void setClient(CuratorFramework client) {
- ZookeeperContext.client = client;
- }
-
- public static boolean isPathExist(String path) {
- try {
- return client.checkExists().forPath(path) != null;
- } catch (Exception e) {
- return false;
- }
- }
-
- /**
- * 是否有子节点
- * @param parentPath
- * @return
- * @throws Exception
- */
- public static boolean hasChildren(String parentPath) throws Exception {
- List children = client.getChildren().forPath(parentPath);
- return !CollectionUtils.isEmpty(children);
- }
-
- /**
- * 创建path,如果path存在不报错,静默返回path名称
- *
- * @param path
- * @param data
- * @return
- * @throws Exception
- */
- public static String createPath(String path, String data) throws Exception {
- if (isPathExist(path)) {
- return path;
- }
- return getClient().create()
- // 如果指定节点的父节点不存在,则Curator将会自动级联创建父节点
- .creatingParentContainersIfNeeded()
- .forPath(path, data.getBytes());
- }
-
- /**
- * 获取子节点信息并监听子节点
- *
- * @param parentPath 父节点路径
- * @param listConsumer 子节点数据
- * @param listener 监听事件
- * @throws Exception
- */
- public static void getChildrenAndListen(String parentPath, Consumer> listConsumer, PathChildrenCacheListener listener) throws Exception {
- // 为子节点添加watcher
- // PathChildrenCache: 监听数据节点的增删改,可以设置触发的事件
- PathChildrenCache childrenCache = new PathChildrenCache(client, parentPath, true);
-
- /**
- * StartMode: 初始化方式
- * POST_INITIALIZED_EVENT:异步初始化,初始化之后会触发事件
- * NORMAL:异步初始化
- * BUILD_INITIAL_CACHE:同步初始化
- */
- childrenCache.start(PathChildrenCache.StartMode.BUILD_INITIAL_CACHE);
-
- // 列出子节点数据列表,需要使用BUILD_INITIAL_CACHE同步初始化模式才能获得,异步是获取不到的
- List childDataList = childrenCache.getCurrentData();
- listConsumer.accept(childDataList);
- log.info("监听子节点增删改,监听路径:{}", parentPath);
- // 监听根节点下面的子节点
- childrenCache.getListenable().addListener(listener);
- }
-
- /**
- * 监听子节点的增删改
- *
- * @param parentPath 父节点路径
- * @param listener
- * @throws Exception
- */
- public static void listenChildren(String parentPath, PathChildrenCacheListener listener) throws Exception {
- // 为子节点添加watcher
- // PathChildrenCache: 监听数据节点的增删改,可以设置触发的事件
- PathChildrenCache childrenCache = new PathChildrenCache(client, parentPath, true);
-
- /**
- * StartMode: 初始化方式
- * POST_INITIALIZED_EVENT:异步初始化,初始化之后会触发事件
- * NORMAL:异步初始化
- * BUILD_INITIAL_CACHE:同步初始化
- */
- childrenCache.start(PathChildrenCache.StartMode.BUILD_INITIAL_CACHE);
- // 监听根节点下面的子节点
- childrenCache.getListenable().addListener(listener);
- }
-
- /**
- * 监听子节点,可以自定义层级
- * @param parentPath 父节点路径
- * @param maxDepth 层级,从1开始。比如当前监听节点/t1,目录最深为/t1/t2/t3/t4,则maxDepth=3,说明下面3级子目录全部监听
- * @param listener
- * @throws Exception
- */
- public static void listenChildren(String parentPath, int maxDepth, TreeCacheListener listener) throws Exception {
- final TreeCache treeCache = TreeCache
- .newBuilder(client, parentPath)
- .setCacheData(true)
- .setMaxDepth(maxDepth)
- .build();
-
- treeCache.getListenable().addListener(listener);
- treeCache.start();
- }
-
-}
diff --git a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/config/RegistryConfig.java b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/config/RegistryConfig.java
deleted file mode 100644
index 1721a2d1..00000000
--- a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/config/RegistryConfig.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.gitee.sop.websiteserver.config;
-
-import com.gitee.sop.registryapi.config.BaseRegistryConfig;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * @author tanghc
- */
-@Configuration
-public class RegistryConfig extends BaseRegistryConfig {
-
-}
\ No newline at end of file
diff --git a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/config/WebsiteConfig.java b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/config/WebsiteConfig.java
index 710b9fac..cdf8d8ae 100644
--- a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/config/WebsiteConfig.java
+++ b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/config/WebsiteConfig.java
@@ -40,6 +40,6 @@ public class WebsiteConfig implements ApplicationRunner {
*/
@Override
public void run(ApplicationArguments args) throws Exception {
- docManager.load(null);
+// docManager.load(null);
}
}
diff --git a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/controller/DocController.java b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/controller/DocController.java
index 957a9275..ed2e972e 100644
--- a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/controller/DocController.java
+++ b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/controller/DocController.java
@@ -4,7 +4,6 @@ import com.gitee.sop.websiteserver.bean.DocInfo;
import com.gitee.sop.websiteserver.manager.DocManager;
import com.gitee.sop.websiteserver.vo.DocBaseInfoVO;
import com.gitee.sop.websiteserver.vo.DocInfoVO;
-import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@@ -58,14 +57,4 @@ public class DocController {
return docManager.getByTitle(title);
}
-
- // 后门地址,可手动更新文档内容,一般情况下用不到
- @GetMapping("/reload")
- public String reload(String pwd) {
- boolean correct = StringUtils.equals(this.pwd, pwd);
- if (correct) {
- docManager.load(null);
- }
- return String.valueOf(correct);
- }
}
diff --git a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/controller/SandboxController.java b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/controller/SandboxController.java
index 794770d4..9c122e86 100644
--- a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/controller/SandboxController.java
+++ b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/controller/SandboxController.java
@@ -1,7 +1,6 @@
package com.gitee.sop.websiteserver.controller;
-import com.gitee.sop.registryapi.bean.HttpTool;
-import com.gitee.sop.registryapi.bean.HttpTool.*;
+import com.gitee.sop.websiteserver.bean.HttpTool;
import com.gitee.sop.websiteserver.sign.AlipayApiException;
import com.gitee.sop.websiteserver.sign.AlipaySignature;
import com.gitee.sop.websiteserver.util.UploadUtil;
@@ -97,10 +96,10 @@ public class SandboxController {
params.put("sign", sign);
Collection uploadFiles = UploadUtil.getUploadFiles(request);
- List files = uploadFiles.stream()
+ List files = uploadFiles.stream()
.map(multipartFile -> {
try {
- return new UploadFile(multipartFile.getName(), multipartFile.getOriginalFilename(), multipartFile.getBytes());
+ return new HttpTool.UploadFile(multipartFile.getName(), multipartFile.getOriginalFilename(), multipartFile.getBytes());
} catch (IOException e) {
log.error("封装文件失败", e);
return null;
@@ -114,7 +113,7 @@ public class SandboxController {
if (!CollectionUtils.isEmpty(files)) {
responseData = httpTool.requestFile(url, params, Collections.emptyMap(), files);
} else {
- responseData = httpTool.request(url, params, Collections.emptyMap(), HTTPMethod.fromValue(httpMethod));
+ responseData = httpTool.request(url, params, Collections.emptyMap(), HttpTool.HTTPMethod.fromValue(httpMethod));
}
result.apiResult = responseData;
return result;
diff --git a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocDiscovery.java b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocDiscovery.java
new file mode 100644
index 00000000..96f9f55a
--- /dev/null
+++ b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocDiscovery.java
@@ -0,0 +1,99 @@
+package com.gitee.sop.websiteserver.manager;
+
+import com.alibaba.nacos.api.exception.NacosException;
+import com.alibaba.nacos.api.naming.NamingService;
+import com.alibaba.nacos.api.naming.pojo.Instance;
+import com.alibaba.nacos.api.naming.pojo.ServiceInfo;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.DigestUtils;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * @author tanghc
+ */
+@Slf4j
+@Service
+public class DocDiscovery {
+
+ private static final String SECRET = "b749a2ec000f4f29";
+
+ private static final int FIVE_SECONDS = 1000 * 5;
+
+ @Autowired
+ private NacosDiscoveryProperties nacosDiscoveryProperties;
+
+ private RestTemplate restTemplate = new RestTemplate();
+
+ private volatile long lastUpdateTime;
+
+ public synchronized void refresh(DocManager docManager) {
+ long now = System.currentTimeMillis();
+ // 5秒内只能执行一次,解决重启应用连续加载4次问题
+ if (now - lastUpdateTime < FIVE_SECONDS) {
+ return;
+ }
+ lastUpdateTime = now;
+ NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
+ List subscribes = null;
+ try {
+ subscribes = namingService.getSubscribeServices();
+ } catch (NacosException e) {
+ log.error("namingService.getSubscribeServices()错误", e);
+ }
+ if (CollectionUtils.isEmpty(subscribes)) {
+ return;
+ }
+ // subscribe
+ String thisServiceId = nacosDiscoveryProperties.getService();
+ for (ServiceInfo serviceInfo : subscribes) {
+ String serviceName = serviceInfo.getName();
+ // 如果是本机服务,跳过
+ if (Objects.equals(thisServiceId, serviceName) || "api-gateway".equalsIgnoreCase(serviceName)) {
+ continue;
+ }
+ try {
+ List allInstances = namingService.getAllInstances(serviceName);
+ if (CollectionUtils.isEmpty(allInstances)) {
+ log.info("{}服务下线,删除文档信息", serviceName);
+ // 如果没有服务列表,则删除所有路由信息
+ docManager.remove(serviceName);
+ } else {
+ for (Instance instance : allInstances) {
+ log.info("加载服务文档,instance:{}", instance);
+ String url = getRouteRequestUrl(instance);
+ ResponseEntity responseEntity = restTemplate.getForEntity(url, String.class);
+ if (responseEntity.getStatusCode() == HttpStatus.OK) {
+ String body = responseEntity.getBody();
+ log.debug("加载{}文档,文档信息:{}", serviceName, body);
+ docManager.addDocInfo(serviceName, body);
+ }
+ }
+ }
+ } catch (NacosException e) {
+ log.error("选择服务实例失败,serviceName:{}", serviceName, e);
+ }
+ }
+ }
+
+ private static String getRouteRequestUrl(Instance instance) {
+ String query = buildQuery(SECRET);
+ return "http://" + instance.getIp() + ":" + instance.getPort() + "/v2/api-docs" + query;
+ }
+
+ private static String buildQuery(String secret) {
+ String time = String.valueOf(System.currentTimeMillis());
+ String source = secret + time + secret;
+ String sign = DigestUtils.md5DigestAsHex(source.getBytes());
+ return "?time=" + time + "&sign=" + sign;
+ }
+
+}
diff --git a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManager.java b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManager.java
index 8716e269..f5490aa8 100644
--- a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManager.java
+++ b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManager.java
@@ -9,9 +9,11 @@ import java.util.Collection;
*/
public interface DocManager {
- void load(String serviceId);
+ void addDocInfo(String serviceId, String docJson);
DocInfo getByTitle(String title);
Collection listAll();
+
+ void remove(String serviceId);
}
diff --git a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManagerImpl.java b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManagerImpl.java
index 925ddd0d..2fb9849b 100644
--- a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManagerImpl.java
+++ b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManagerImpl.java
@@ -3,119 +3,54 @@ package com.gitee.sop.websiteserver.manager;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
-import com.gitee.sop.registryapi.bean.ServiceInfo;
-import com.gitee.sop.registryapi.bean.ServiceInstance;
-import com.gitee.sop.registryapi.service.RegistryService;
import com.gitee.sop.websiteserver.bean.DocInfo;
-import com.gitee.sop.websiteserver.bean.ZookeeperContext;
-import lombok.Data;
import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.math.NumberUtils;
-import org.apache.curator.framework.recipes.cache.ChildData;
-import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.core.env.Environment;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
+import org.springframework.cloud.client.discovery.event.HeartbeatEvent;
+import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
-import org.springframework.util.StringUtils;
-import org.springframework.web.client.RestTemplate;
-import javax.annotation.PostConstruct;
+import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
-import java.util.concurrent.DelayQueue;
-import java.util.concurrent.Delayed;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
+import java.util.Objects;
/**
* @author tanghc
*/
@Service
@Slf4j
-public class DocManagerImpl implements DocManager {
+public class DocManagerImpl implements DocManager, ApplicationListener {
// key:title
private Map docDefinitionMap = new HashMap<>();
- private RestTemplate restTemplate = new RestTemplate();
+ /**
+ * KEY:serviceId, value: md5
+ */
+ private Map serviceIdMd5Map = new HashMap<>();
private DocParser swaggerDocParser = new SwaggerDocParser();
private DocParser easyopenDocParser = new EasyopenDocParser();
- private ExecutorService executorService = Executors.newSingleThreadExecutor();
-
- private DelayQueue queue = new DelayQueue<>();
-
- private String secret = "b749a2ec000f4f29";
-
@Autowired
- private Environment environment;
-
- @Autowired
- private RegistryService registryService;
-
- @Value("${doc.refresh-seconds:60}")
- private String refreshSeconds;
+ private DocDiscovery docDiscovery;
@Override
- public void load(String serviceId) {
- try {
- List serviceInfoList = registryService.listAllService(1, 9999);
- serviceInfoList
- .stream()
- // 网关没有文档提供,需要排除
- .filter(serviceInfo -> !"API-GATEWAY".equalsIgnoreCase(serviceInfo.getServiceId()))
- .filter(serviceInfo -> !serviceInfo.getInstances().isEmpty())
- .filter(serviceInfo -> {
- if (StringUtils.isEmpty(serviceId)) {
- return true;
- }
- return serviceId.equalsIgnoreCase(serviceInfo.getServiceId());
- })
- .map(serviceInfo -> serviceInfo.getInstances().get(0))
- .collect(Collectors.toList())
- .forEach(this::loadDocInfo);
- } catch (Exception e) {
- log.error("加载失败", e);
+ public void addDocInfo(String serviceId, String docInfoJson) {
+ String newMd5 = DigestUtils.md5DigestAsHex(docInfoJson.getBytes(StandardCharsets.UTF_8));
+ String md5 = serviceIdMd5Map.putIfAbsent(serviceId, newMd5);
+ if (Objects.equals(newMd5, md5)) {
+ return;
}
- }
-
- protected void loadDocInfo(ServiceInstance serviceInstance) {
- String query = this.buildQuery();
- String url = "http://" + serviceInstance.getIp() + ":" + serviceInstance.getPort() + "/v2/api-docs" + query;
- try {
- log.info("读取swagger文档,serviceId:{}, url:{}", serviceInstance.getServiceId(), url);
- ResponseEntity entity = restTemplate.getForEntity(url, String.class);
- if (entity.getStatusCode() != HttpStatus.OK) {
- throw new IllegalAccessException("无权访问");
- }
- String docInfoJson = entity.getBody();
- JSONObject docRoot = JSON.parseObject(docInfoJson, Feature.OrderedField, Feature.DisableCircularReferenceDetect);
- DocParser docParser = this.buildDocParser(docRoot);
- DocInfo docInfo = docParser.parseJson(docRoot);
- docInfo.setServiceId(serviceInstance.getServiceId());
- docDefinitionMap.put(docInfo.getTitle(), docInfo);
- } catch (Exception e) {
- // 这里报错可能是因为有些微服务没有配置swagger文档,导致404访问不到
- // 这里catch跳过即可
- log.warn("读取文档失败, url:{}, msg:{}", url, e.getMessage());
- }
- }
-
- protected String buildQuery() {
- String time = String.valueOf(System.currentTimeMillis());
- String source = secret + time + secret;
- String sign = DigestUtils.md5DigestAsHex(source.getBytes());
- return "?time=" + time + "&sign=" + sign;
+ JSONObject docRoot = JSON.parseObject(docInfoJson, Feature.OrderedField, Feature.DisableCircularReferenceDetect);
+ DocParser docParser = this.buildDocParser(docRoot);
+ DocInfo docInfo = docParser.parseJson(docRoot);
+ docInfo.setServiceId(serviceId);
+ docDefinitionMap.put(docInfo.getTitle(), docInfo);
}
protected DocParser buildDocParser(JSONObject rootDoc) {
@@ -137,143 +72,14 @@ public class DocManagerImpl implements DocManager {
return docDefinitionMap.values();
}
- @PostConstruct
- protected void after() throws Exception {
- this.listenServiceId();
- }
-
- /**
- * 监听serviceId更改
- *
- * @throws Exception
- */
- protected void listenServiceId() throws Exception {
-
- executorService.execute(new Consumer(queue, this));
-
- ZookeeperContext.setEnvironment(environment);
- String serviceTempRootPath = ZookeeperContext.getServiceTempRootPath();
- ZookeeperContext.createPath(serviceTempRootPath, "{}");
- // 如果节点内容有变化则自动更新文档
-
- ZookeeperContext.getChildrenAndListen(serviceTempRootPath, childDataList -> {
- for (ChildData childData : childDataList) {
- String serviceIdPath = childData.getPath();
- try {
- boolean hasChildren = ZookeeperContext.hasChildren(serviceIdPath);
- if (hasChildren) {
- log.info("加载文档服务器,path:{}", serviceIdPath);
- listenServiceIdPath(serviceIdPath);
- }
- } catch (Exception e) {
- log.error("监听路径失败,serviceIdPath:{}", serviceIdPath);
- }
- }
- }, (client, event) -> {
- PathChildrenCacheEvent.Type type = event.getType();
- if (type == PathChildrenCacheEvent.Type.CHILD_ADDED) {
- String serviceIdPath = event.getData().getPath();
- log.info("新增文档服务器,path:{}", serviceIdPath);
- listenServiceIdPath(serviceIdPath);
- }
- });
- }
-
- private void listenServiceIdPath(String serviceIdPath) throws Exception {
- ZookeeperContext.listenChildren(serviceIdPath, (client, event) -> {
- String path = event.getData().getPath();
- PathChildrenCacheEvent.Type type = event.getType();
- log.info("服务节点变更,path:{}, eventType:{}", path, event.getType().name());
- if (type == PathChildrenCacheEvent.Type.CHILD_ADDED
- || type == PathChildrenCacheEvent.Type.CHILD_UPDATED) {
- byte[] data = event.getData().getData();
- String serviceInfoJson = new String(data);
- if (StringUtils.isEmpty(serviceInfoJson)) {
- return;
- }
- ZKServiceInfo serviceInfo = JSON.parseObject(serviceInfoJson, ZKServiceInfo.class);
- String serviceId = serviceInfo.getServiceId();
- int delaySeconds = NumberUtils.toInt(refreshSeconds, 60);
- log.info("微服务[{}]推送更新,{}秒后加载文档内容", serviceId, delaySeconds);
- long id = System.currentTimeMillis();
- Msg msg = new Msg(id, delaySeconds * 1000);
- msg.serviceId = serviceId;
- // 延迟20秒执行
- queue.offer(msg);
- } else if (event.getType() == PathChildrenCacheEvent.Type.CHILD_REMOVED) {
- byte[] data = event.getData().getData();
- String serviceInfoJson = new String(data);
- ZKServiceInfo serviceInfo = JSON.parseObject(serviceInfoJson, ZKServiceInfo.class);
- String serviceId = serviceInfo.getServiceId();
- boolean hasChildren = ZookeeperContext.hasChildren(serviceIdPath);
- // 如果没有子节点就删除
- if (!hasChildren) {
- log.info("服务节点已删除,删除对应文档信息,path:{}", event.getData().getPath());
- removeDoc(serviceId);
- }
- }
- });
- }
-
- public void removeDoc(String serviceId) {
+ @Override
+ public void remove(String serviceId) {
docDefinitionMap.entrySet().removeIf(entry -> serviceId.equalsIgnoreCase(entry.getValue().getServiceId()));
}
- static class Msg implements Delayed {
- private long id;
- private long delay;
- private String serviceId;
-
- // 自定义实现比较方法返回 1 0 -1三个参数
-
-
- public Msg(long id, long delay) {
- this.id = id;
- this.delay = delay + System.currentTimeMillis();
- }
-
- @Override
- public int compareTo(Delayed delayed) {
- Msg msg = (Msg) delayed;
- return Long.compare(this.id, msg.id);
- }
-
- // 延迟任务是否到时就是按照这个方法判断如果返回的是负数则说明到期否则还没到期
- @Override
- public long getDelay(TimeUnit unit) {
- return unit.convert(this.delay - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
- }
+ @Override
+ public void onApplicationEvent(HeartbeatEvent heartbeatEvent) {
+ docDiscovery.refresh(this);
}
- @Data
- static class ZKServiceInfo {
- /** 服务名称,对应spring.application.name */
- private String serviceId;
-
- private String description;
- }
-
- @Slf4j
- static class Consumer implements Runnable {
- private DelayQueue queue;
- private DocManager docManager;
-
- public Consumer(DelayQueue queue, DocManager docManager) {
- this.queue = queue;
- this.docManager = docManager;
- }
-
- @Override
- public void run() {
- while (true) {
- try {
- Msg msg = queue.take();
- log.info("延迟队列触发--重新加载文档信息");
- docManager.load(msg.serviceId);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
}
diff --git a/sop-website/website-server/src/main/resources/application-dev.properties b/sop-website/website-server/src/main/resources/application-dev.properties
index 59fabaed..c8a6582f 100644
--- a/sop-website/website-server/src/main/resources/application-dev.properties
+++ b/sop-website/website-server/src/main/resources/application-dev.properties
@@ -2,9 +2,6 @@ server.port=8083
spring.application.name=website-server
# ------- 需要改的配置 -------
-
-# eureka注册中心地址
-eureka.url=http://localhost:1111/eureka/
# zookeeper地址
zookeeper.url=localhost:2181
# nacos地址
@@ -12,15 +9,8 @@ nacos.url=127.0.0.1:8848
# ------- 需要改的配置end -------
-# eureka注册中心地址,这里只是参数,并不会去注册
-registry.eureka-server-addr=${eureka.url}
-# nacos服务器地址
-registry.nacos-server-addr=${nacos.url}
-# 使用eureka,填:eureka,使用nacos填:nacos
-registry.name=nacos
-
-# zookeeper配置
-spring.cloud.zookeeper.connect-string=${zookeeper.url}
+# nacos cloud配置
+spring.cloud.nacos.discovery.server-addr=${nacos.url}
# 测试环境
api.url-test=http://api-test.yourdomain.com/api