diff --git a/sop-admin/sop-admin-front/pages/service/routeManager.js b/sop-admin/sop-admin-front/pages/service/routeManager.js
index 62022553..d3fcf5bd 100644
--- a/sop-admin/sop-admin-front/pages/service/routeManager.js
+++ b/sop-admin/sop-admin-front/pages/service/routeManager.js
@@ -5,6 +5,7 @@ lib.importJs('../../assets/js/routerole.js')
,'1': '
已启用'
,'2': '
已禁用'
}
+ var element = layui.element;
var form = layui.form;
var updateForm = layui.Form('updateForm');
var addForm = layui.Form('addForm');
@@ -50,43 +51,30 @@ lib.importJs('../../assets/js/routerole.js')
return false;
});
+ element.on('tab(serviceTabFilter)', function(data){
+ loadRouteTable(this.innerHTML);
+ });
- function initTree() {
+
+ function initServiceTab() {
ApiUtil.post('service.list', {}, function (resp) {
var serviceList = resp.data;
- var children = [];
+ var html = [];
for (var i = 0; i < serviceList.length; i++) {
var serviceInfo = serviceList[i];
- children.push({
- id: i + 1,
- name: serviceInfo.serviceId
- })
+ var clazz = i === 0 ? 'class="layui-this"' : '';
+ html.push('
' + serviceInfo.serviceId + '');
}
+ $('#serviceTab').html(html.join(''));
- layui.tree({
- elem: '#leftTree' //传入元素选择器
- , nodes: [{ //节点
- name: '服务列表'
- , spread: true // 展开
- , children: children
- }]
- , click: function (node) {
- if (node.id) {
- reloadRightPart(node)
- }
- }
- });
+ if (serviceList.length > 0) {
+ loadRouteTable(serviceList[0].serviceId);
+ }
});
}
- /**
- * 更新右边部分
- * @param node 树节点
- */
- function reloadRightPart(node) {
- $('#optTip').hide();
- $('#rightPart').show();
- var serviceId = node.name;
+
+ function loadRouteTable(serviceId) {
currentServiceId = serviceId;
searchTable({
serviceId: serviceId
@@ -174,7 +162,7 @@ lib.importJs('../../assets/js/routerole.js')
layer.open({
type: 1
,title: '修改路由' + smTitle
- ,area: ['500px', '460px']
+ ,area: ['500px', '350px']
,content: $('#updateWin') //这里content是一个DOM,注意:最好该元素要存放在body最外层,否则可能被其它的相对元素所影响
});
} else if (event === 'auth') {
@@ -210,7 +198,7 @@ lib.importJs('../../assets/js/routerole.js')
layer.open({
type: 1
,title: '添加路由' + smTitle
- ,area: ['500px', '460px']
+ ,area: ['500px', '350px']
,content: $('#addWin')
});
}
@@ -218,7 +206,7 @@ lib.importJs('../../assets/js/routerole.js')
return routeTable;
}
- initTree();
+ initServiceTab();
RouteRole.loadAllRole(form, 'roleArea');
diff --git a/sop-admin/sop-admin-server/pom.xml b/sop-admin/sop-admin-server/pom.xml
index 0182ade8..71c4a94d 100644
--- a/sop-admin/sop-admin-server/pom.xml
+++ b/sop-admin/sop-admin-server/pom.xml
@@ -37,7 +37,7 @@
net.oschina.durcframework
easyopen-spring-boot-starter
- 1.16.0
+ 1.16.2
diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/result/IsvFormVO.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/result/IsvFormVO.java
index 744ec68b..262fc25b 100644
--- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/result/IsvFormVO.java
+++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/result/IsvFormVO.java
@@ -8,10 +8,10 @@ import lombok.Data;
*/
@Data
public class IsvFormVO {
- @ApiDocField(description = "appKey")
+ @ApiDocField(description = "appKey", example = "aaaa")
private String appKey;
- @ApiDocField(description = "secret")
+ @ApiDocField(description = "secret", example = "bbbb")
private String secret;
@ApiDocField(description = "pubKey")
diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/result/IsvVO.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/result/IsvVO.java
index 1206677b..ed2057fd 100644
--- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/result/IsvVO.java
+++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/result/IsvVO.java
@@ -12,15 +12,15 @@ import java.util.List;
@Data
public class IsvVO {
/** 数据库字段:id */
- @ApiDocField(description = "id")
+ @ApiDocField(description = "id", example = "1")
private Long id;
/** appKey, 数据库字段:app_key */
- @ApiDocField(description = "appKey")
+ @ApiDocField(description = "appKey", example = "aaaa")
private String appKey;
/** secret, 数据库字段:secret */
- @ApiDocField(description = "appKey")
+ @ApiDocField(description = "secret", example = "bbbb")
private String secret;
/** 公钥, 数据库字段:pub_key */
diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LimitApi.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LimitApi.java
new file mode 100644
index 00000000..0abe386c
--- /dev/null
+++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LimitApi.java
@@ -0,0 +1,115 @@
+package com.gitee.sop.adminserver.api.service;
+
+import com.gitee.easyopen.annotation.Api;
+import com.gitee.easyopen.annotation.ApiService;
+import com.gitee.easyopen.doc.annotation.ApiDoc;
+import com.gitee.easyopen.doc.annotation.ApiDocMethod;
+import com.gitee.easyopen.exception.ApiException;
+import com.gitee.easyopen.util.CopyUtil;
+import com.gitee.fastmybatis.core.query.Query;
+import com.gitee.sop.adminserver.api.service.param.LimitParam;
+import com.gitee.sop.adminserver.api.service.param.RouteSearchParam;
+import com.gitee.sop.adminserver.api.service.result.LimitVO;
+import com.gitee.sop.adminserver.bean.GatewayRouteDefinition;
+import com.gitee.sop.adminserver.bean.RouteConfigDto;
+import com.gitee.sop.adminserver.common.LimitEnum;
+import com.gitee.sop.adminserver.entity.ConfigRouteLimit;
+import com.gitee.sop.adminserver.mapper.ConfigRouteLimitMapper;
+import com.gitee.sop.adminserver.service.RouteConfigService;
+import com.gitee.sop.adminserver.service.RouteService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * 限流
+ *
+ * @author tanghc
+ */
+@ApiService
+@ApiDoc("服务管理")
+@Slf4j
+public class LimitApi {
+
+ @Autowired
+ RouteService routeService;
+
+ @Autowired
+ RouteConfigService routeConfigService;
+
+ @Autowired
+ ConfigRouteLimitMapper configRouteLimitMapper;
+
+ @Api(name = "route.limit.list")
+ @ApiDocMethod(description = "限流列表", elementClass = LimitVO.class)
+ List listLimit(RouteSearchParam param) throws Exception {
+ List routeDefinitionList = routeService.getRouteDefinitionList(param);
+ List routeIdList = getRouteIdList(routeDefinitionList);
+ // key:routeId
+ Map routeLimitMap = getStoreConfigRouteLimit(routeIdList);
+ List gatewayRouteDefinitions = routeDefinitionList
+ .stream()
+ .map(gatewayRouteDefinition -> {
+ LimitVO vo = new LimitVO();
+ CopyUtil.copyProperties(gatewayRouteDefinition, vo);
+ ConfigRouteLimit configRouteLimit = routeLimitMap.getOrDefault(gatewayRouteDefinition.getId(), getDefaultLimit());
+ CopyUtil.copyPropertiesIgnoreNull(configRouteLimit, vo);
+ return vo;
+ })
+ .collect(Collectors.toList());
+ return gatewayRouteDefinitions;
+ }
+
+ private List getRouteIdList(List routeDefinitionList) {
+ return routeDefinitionList
+ .stream()
+ .map(GatewayRouteDefinition::getId)
+ .collect(Collectors.toList());
+ }
+
+ private Map getStoreConfigRouteLimit(List routeIdList) {
+ Query query = new Query();
+ query.in("route_id", routeIdList);
+ // key:routeId
+ Map routeLimitMap = configRouteLimitMapper.list(query)
+ .stream()
+ .collect(Collectors.toMap(ConfigRouteLimit::getRouteId, Function.identity()));
+ return routeLimitMap;
+ }
+
+ private ConfigRouteLimit getDefaultLimit() {
+ ConfigRouteLimit configRouteLimit = new ConfigRouteLimit();
+ configRouteLimit.setType(LimitEnum.TYPE_LEAKY_BUCKET.getVal());
+ configRouteLimit.setLimitStatus(LimitEnum.STATUS_CLOSE.getVal());
+ return configRouteLimit;
+ }
+
+ @Api(name = "route.limit.update")
+ @ApiDocMethod(description = "修改限流")
+ @Transactional(rollbackFor = Exception.class)
+ public void updateLimtit(LimitParam param) {
+ String routeId = param.getRouteId();
+ ConfigRouteLimit configRouteLimit = configRouteLimitMapper.getByColumn("route_id", routeId);
+ if (configRouteLimit == null) {
+ configRouteLimit = new ConfigRouteLimit();
+ CopyUtil.copyPropertiesIgnoreNull(param, configRouteLimit);
+ configRouteLimitMapper.save(configRouteLimit);
+ } else {
+ CopyUtil.copyPropertiesIgnoreNull(param, configRouteLimit);
+ configRouteLimitMapper.updateIgnoreNull(configRouteLimit);
+ }
+ RouteConfigDto routeConfigDto = new RouteConfigDto();
+ CopyUtil.copyPropertiesIgnoreNull(param, routeConfigDto);
+ try {
+ routeConfigService.sendRouteConfigMsg(routeConfigDto);
+ } catch (Exception e) {
+ log.error("推送限流消息错误, param:{}", param, e);
+ throw new ApiException("修改失败,请查看日志");
+ }
+ }
+}
diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/RouteApi.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/RouteApi.java
index 252eeb23..bd0b4ef4 100644
--- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/RouteApi.java
+++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/RouteApi.java
@@ -6,6 +6,7 @@ import com.gitee.easyopen.annotation.ApiService;
import com.gitee.easyopen.doc.annotation.ApiDoc;
import com.gitee.easyopen.doc.annotation.ApiDocMethod;
import com.gitee.easyopen.exception.ApiException;
+import com.gitee.easyopen.util.CopyUtil;
import com.gitee.fastmybatis.core.query.Query;
import com.gitee.sop.adminserver.api.isv.result.RoleVO;
import com.gitee.sop.adminserver.api.service.param.RouteParam;
@@ -14,23 +15,26 @@ import com.gitee.sop.adminserver.api.service.param.RouteSearchParam;
import com.gitee.sop.adminserver.api.service.result.RouteVO;
import com.gitee.sop.adminserver.api.service.result.ServiceInfo;
import com.gitee.sop.adminserver.bean.GatewayRouteDefinition;
+import com.gitee.sop.adminserver.bean.RouteConfigDto;
import com.gitee.sop.adminserver.bean.ZookeeperContext;
+import com.gitee.sop.adminserver.entity.ConfigRouteBase;
import com.gitee.sop.adminserver.entity.PermRole;
import com.gitee.sop.adminserver.entity.PermRolePermission;
+import com.gitee.sop.adminserver.mapper.ConfigRouteBaseMapper;
import com.gitee.sop.adminserver.mapper.PermRoleMapper;
import com.gitee.sop.adminserver.mapper.PermRolePermissionMapper;
+import com.gitee.sop.adminserver.service.RouteConfigService;
import com.gitee.sop.adminserver.service.RoutePermissionService;
+import com.gitee.sop.adminserver.service.RouteService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
-import org.apache.curator.framework.recipes.cache.ChildData;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
@@ -49,36 +53,24 @@ public class RouteApi {
@Autowired
PermRoleMapper permRoleMapper;
+ @Autowired
+ ConfigRouteBaseMapper configRouteBaseMapper;
+
@Autowired
RoutePermissionService routePermissionService;
+ @Autowired
+ RouteConfigService routeConfigService;
+
+ @Autowired
+ RouteService routeService;
+
@Api(name = "route.list")
@ApiDocMethod(description = "路由列表")
List listRoute(RouteSearchParam param) throws Exception {
- if (StringUtils.isBlank(param.getServiceId())) {
- return Collections.emptyList();
- }
-
- String searchPath = ZookeeperContext.getSopRouteRootPath() + "/" + param.getServiceId();
-
- List childDataList = ZookeeperContext.getChildrenData(searchPath);
-
- List routeDefinitionList = childDataList.stream()
- .map(childData -> {
- String serviceNodeData = new String(childData.getData());
- GatewayRouteDefinition routeDefinition = JSON.parseObject(serviceNodeData, GatewayRouteDefinition.class);
- return routeDefinition;
- })
- .filter(gatewayRouteDefinition -> {
- boolean isRoute = gatewayRouteDefinition.getOrder() != Integer.MIN_VALUE;
- String id = param.getId();
- if (StringUtils.isBlank(id)) {
- return isRoute;
- } else {
- return isRoute && gatewayRouteDefinition.getId().contains(id);
- }
- })
- .map(gatewayRouteDefinition->{
+ List routeDefinitionList = routeService.getRouteDefinitionList(param)
+ .stream()
+ .map(gatewayRouteDefinition -> {
RouteVO vo = new RouteVO();
BeanUtils.copyProperties(gatewayRouteDefinition, vo);
vo.setRoles(this.getRouteRole(gatewayRouteDefinition.getId()));
@@ -96,8 +88,10 @@ public class RouteApi {
String zookeeperRoutePath = serviceIdPath + "/" + param.getId();
String data = ZookeeperContext.getData(zookeeperRoutePath);
GatewayRouteDefinition routeDefinition = JSON.parseObject(data, GatewayRouteDefinition.class);
- BeanUtils.copyProperties(param, routeDefinition);
+ CopyUtil.copyPropertiesIgnoreNull(param, routeDefinition);
ZookeeperContext.updatePathData(zookeeperRoutePath, JSON.toJSONString(routeDefinition));
+
+ this.updateRouteConfig(param);
}
@Api(name = "route.add")
@@ -109,7 +103,7 @@ public class RouteApi {
throw new ApiException("id已存在");
}
GatewayRouteDefinition routeDefinition = new GatewayRouteDefinition();
- BeanUtils.copyProperties(param, routeDefinition);
+ CopyUtil.copyPropertiesIgnoreNull(param, routeDefinition);
ZookeeperContext.createNewData(zookeeperRoutePath, JSON.toJSONString(routeDefinition));
ServiceInfo serviceInfo = new ServiceInfo();
serviceInfo.setServiceId(param.getServiceId());
@@ -118,6 +112,37 @@ public class RouteApi {
serviceInfo.setCreateTime(now);
serviceInfo.setUpdateTime(now);
ZookeeperContext.updatePathData(serviceIdPath, JSON.toJSONString(serviceInfo));
+
+ this.updateRouteConfig(param);
+ }
+
+ private void updateRouteConfig(RouteParam param) {
+ try {
+ String routeId = param.getId();
+ ConfigRouteBase configRouteBase = configRouteBaseMapper.getByColumn("route_id", routeId);
+ boolean doSave = configRouteBase == null;
+ if (doSave) {
+ configRouteBase = new ConfigRouteBase();
+ configRouteBase.setRouteId(param.getId());
+ }
+ configRouteBase.setStatus(param.getStatus().byteValue());
+
+ int i = doSave ? configRouteBaseMapper.save(configRouteBase)
+ : configRouteBaseMapper.update(configRouteBase);
+
+ if (i > 0) {
+ this.sendMsg(param);
+ }
+ } catch (Exception e) {
+ log.error("发送msg失败", e);
+ }
+ }
+
+ private void sendMsg(RouteParam param) throws Exception {
+ RouteConfigDto routeConfigDto = new RouteConfigDto();
+ routeConfigDto.setRouteId(param.getId());
+ routeConfigDto.setStatus(param.getStatus());
+ routeConfigService.sendRouteConfigMsg(routeConfigDto);
}
@Api(name = "route.role.get")
@@ -166,9 +191,10 @@ public class RouteApi {
}
try {
- routePermissionService.sendRoutePermissionReloadToZookeeper();
+ routePermissionService.sendRoutePermissionReloadMsg();
} catch (Exception e) {
- log.info("消息推送--路由权限(reload)失败",e);
+ log.info("消息推送--路由权限(reload)失败", e);
+ throw new ApiException("修改失败,请查看日志");
}
}
diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/LimitParam.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/LimitParam.java
new file mode 100644
index 00000000..f9e5ea62
--- /dev/null
+++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/LimitParam.java
@@ -0,0 +1,45 @@
+package com.gitee.sop.adminserver.api.service.param;
+
+import com.gitee.easyopen.doc.annotation.ApiDocField;
+import com.gitee.sop.adminserver.bean.GatewayRouteDefinition;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+/**
+ * 限流
+ * @author tanghc
+ */
+@Data
+public class LimitParam {
+ @ApiDocField(description = "routeId")
+ @NotBlank
+ private String routeId;
+
+ /** 限流策略,1:漏桶策略,2:令牌桶策略, 数据库字段:type */
+ @ApiDocField(description = "限流策略,1:漏桶策略,2:令牌桶策略")
+ @NotNull
+ private Byte type;
+
+ /** 每秒可处理请求数, 数据库字段:exec_count_per_second */
+ @ApiDocField(description = "每秒可处理请求数")
+ private Integer execCountPerSecond;
+
+ /** 返回的错误码, 数据库字段:limit_code */
+ @ApiDocField(description = "返回的错误码")
+ private String limitCode;
+
+ /** 返回的错误信息, 数据库字段:limit_msg */
+ @ApiDocField(description = "返回的错误信息")
+ private String limitMsg;
+
+ /** 令牌桶容量, 数据库字段:token_bucket_count */
+ @ApiDocField(description = "令牌桶容量")
+ private Integer tokenBucketCount;
+
+ /** 1:开启,0关闭, 数据库字段:limit_status */
+ @ApiDocField(description = "1:开启,0关闭")
+ @NotNull
+ private Byte limitStatus;
+}
diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/RouteParam.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/RouteParam.java
index f7f786cf..3ea6bbd4 100644
--- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/RouteParam.java
+++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/RouteParam.java
@@ -38,14 +38,6 @@ public class RouteParam {
@ApiDocField(description = "路由path")
private String path;
-
- /**
- * 是否忽略验证,业务参数验证除外
- */
- @NotNull
- @ApiDocField(description = "是否忽略验证,1:是,0:否")
- private Integer ignoreValidate;
-
/**
* 状态
*/
@@ -53,10 +45,4 @@ public class RouteParam {
@ApiDocField(description = "状态,0:审核,1:启用,2:禁用")
private Integer status;
- /**
- * 状态
- */
- @NotNull
- @ApiDocField(description = "是否合并结果,1:是,0:否")
- private Integer mergeResult;
}
diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/RouteSearchParam.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/RouteSearchParam.java
index 39904ef6..61b9d7c2 100644
--- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/RouteSearchParam.java
+++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/RouteSearchParam.java
@@ -4,12 +4,18 @@ import com.gitee.easyopen.doc.annotation.ApiDocField;
import lombok.Getter;
import lombok.Setter;
+import javax.validation.constraints.NotBlank;
+
/**
* @author tanghc
*/
@Getter
@Setter
-public class RouteSearchParam extends ServiceSearchParam {
- @ApiDocField(description = "id")
+public class RouteSearchParam {
+ @ApiDocField(description = "服务名serviceId")
+ @NotBlank(message = "serviceId不能为空")
+ private String serviceId;
+
+ @ApiDocField(description = "路由id")
private String id;
}
diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/ServiceSearchParam.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/ServiceSearchParam.java
index f8db7cff..34535ad6 100644
--- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/ServiceSearchParam.java
+++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/ServiceSearchParam.java
@@ -4,6 +4,8 @@ import com.gitee.easyopen.doc.annotation.ApiDocField;
import lombok.Getter;
import lombok.Setter;
+import javax.validation.constraints.NotBlank;
+
/**
* @author tanghc
*/
@@ -11,6 +13,6 @@ import lombok.Setter;
@Setter
public class ServiceSearchParam {
- @ApiDocField(description = "serviceId")
+ @ApiDocField(description = "服务名serviceId")
private String serviceId;
}
diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/LimitVO.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/LimitVO.java
new file mode 100644
index 00000000..08ca8611
--- /dev/null
+++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/LimitVO.java
@@ -0,0 +1,54 @@
+package com.gitee.sop.adminserver.api.service.result;
+
+import com.gitee.easyopen.doc.annotation.ApiDocField;
+import lombok.Data;
+
+/**
+ * 限流
+ *
+ * @author tanghc
+ */
+@Data
+public class LimitVO {
+ @ApiDocField(description = "路由id")
+ private String id;
+
+ @ApiDocField(description = "serviceId")
+ private String serviceId;
+
+ /**
+ * 限流策略,1:漏桶策略,2:令牌桶策略, 数据库字段:type
+ */
+ @ApiDocField(description = "限流策略,1:漏桶策略,2:令牌桶策略")
+ private Byte type;
+
+ /**
+ * 每秒可处理请求数, 数据库字段:exec_count_per_second
+ */
+ @ApiDocField(description = "每秒可处理请求数")
+ private Integer execCountPerSecond;
+
+ /**
+ * 返回的错误码, 数据库字段:limit_code
+ */
+ @ApiDocField(description = "返回的错误码")
+ private String limitCode;
+
+ /**
+ * 返回的错误信息, 数据库字段:limit_msg
+ */
+ @ApiDocField(description = "返回的错误信息")
+ private String limitMsg;
+
+ /**
+ * 令牌桶容量, 数据库字段:token_bucket_count
+ */
+ @ApiDocField(description = "令牌桶容量")
+ private Integer tokenBucketCount;
+
+ /**
+ * 1:开启,0关闭, 数据库字段:limit_status
+ */
+ @ApiDocField(description = "1:开启,0关闭")
+ private Byte limitStatus;
+}
diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/system/param/LoginForm.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/system/param/LoginForm.java
index cfb7856b..08da9e47 100644
--- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/system/param/LoginForm.java
+++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/system/param/LoginForm.java
@@ -1,9 +1,17 @@
package com.gitee.sop.adminserver.api.system.param;
+import com.gitee.easyopen.doc.annotation.ApiDocField;
import lombok.Data;
+import javax.validation.constraints.NotBlank;
+
@Data
public class LoginForm {
+ @NotBlank(message = "用户名不能为空")
+ @ApiDocField(description = "用户名", required = true)
private String username;
+
+ @NotBlank(message = "密码不能为空")
+ @ApiDocField(description = "密码", required = true)
private String password;
}
\ No newline at end of file
diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/GatewayRouteDefinition.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/GatewayRouteDefinition.java
index e40d5831..6b130a49 100644
--- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/GatewayRouteDefinition.java
+++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/GatewayRouteDefinition.java
@@ -1,5 +1,6 @@
package com.gitee.sop.adminserver.bean;
+import com.gitee.easyopen.doc.annotation.ApiDocField;
import lombok.Data;
import java.util.ArrayList;
@@ -13,6 +14,7 @@ public class GatewayRouteDefinition {
/**
* 路由的Id
*/
+ @ApiDocField(description = "路由id")
private String id = "";
/**
@@ -28,11 +30,13 @@ public class GatewayRouteDefinition {
/**
* 路由规则转发的目标uri
*/
+ @ApiDocField(description = "uri")
private String uri;
/**
* uri后面跟的path
*/
+ @ApiDocField(description = "path")
private String path;
/**
@@ -43,20 +47,24 @@ public class GatewayRouteDefinition {
/**
* 是否忽略验证,业务参数验证除外
*/
+ @ApiDocField(description = "是否忽略验证,业务参数验证除外,1:忽略,0:不忽略")
private int ignoreValidate;
/**
* 状态,0:待审核,1:启用,2:禁用
*/
+ @ApiDocField(description = "状态,0:待审核,1:启用,2:禁用")
private int status = 1;
/**
* 合并结果
*/
+ @ApiDocField(description = "合并结果,1:合并,2:不合并")
private int mergeResult = 1;
/**
* 是否需要授权才能访问
*/
+ @ApiDocField(description = "是否需要授权才能访问,1:是,2:否")
private int permission;
}
\ No newline at end of file
diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/RouteConfigDto.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/RouteConfigDto.java
new file mode 100644
index 00000000..5455f487
--- /dev/null
+++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/RouteConfigDto.java
@@ -0,0 +1,37 @@
+package com.gitee.sop.adminserver.bean;
+
+import lombok.Data;
+
+/**
+ * @author tanghc
+ */
+@Data
+public class RouteConfigDto {
+
+ private String routeId;
+
+ /** 限流策略,1:漏桶策略,2:令牌桶策略, 数据库字段:type */
+ private Byte type;
+
+ /** 每秒可处理请求数, 数据库字段:exec_count_per_second */
+ private Integer execCountPerSecond;
+
+ /** 返回的错误码, 数据库字段:limit_code */
+ private String limitCode;
+
+ /** 返回的错误信息, 数据库字段:limit_msg */
+ private String limitMsg;
+
+ /** 令牌桶容量, 数据库字段:token_bucket_count */
+ private Integer tokenBucketCount;
+
+ /** 限流开启状态,1:开启,0关闭, 数据库字段:limit_status */
+ private Byte limitStatus;
+
+ /**
+ * 状态,0:待审核,1:启用,2:禁用
+ */
+ private Integer status;
+
+
+}
diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ZookeeperContext.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ZookeeperContext.java
index 410c6801..a2122c75 100644
--- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ZookeeperContext.java
+++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ZookeeperContext.java
@@ -67,6 +67,10 @@ public class ZookeeperContext {
return SOP_MSG_CHANNEL_PATH + "/isv-route-permission";
}
+ public static String getRouteConfigChannelPath() {
+ return SOP_MSG_CHANNEL_PATH + "/route-conf";
+ }
+
public static CuratorFramework getClient() {
return client;
}
diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/common/LimitEnum.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/common/LimitEnum.java
new file mode 100644
index 00000000..e516dbf9
--- /dev/null
+++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/common/LimitEnum.java
@@ -0,0 +1,36 @@
+package com.gitee.sop.adminserver.common;
+
+/**
+ * 限流
+ * @author tanghc
+ */
+public enum LimitEnum {
+ /**
+ * 限流策略,1:漏桶策略
+ */
+ TYPE_LEAKY_BUCKET((byte) 1),
+ /**
+ * 限流策略,2:令牌桶策略
+ */
+ TYPE_TOKEN_BUCKET((byte) 2),
+ /**
+ * 1:开启
+ */
+ STATUS_OPEN((byte) 1),
+ /**
+ * 0关闭
+ */
+ STATUS_CLOSE((byte) 0),
+
+ ;
+
+ LimitEnum(byte val) {
+ this.val = val;
+ }
+
+ private byte val;
+
+ public byte getVal() {
+ return val;
+ }
+}
diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/entity/ConfigRouteBase.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/entity/ConfigRouteBase.java
new file mode 100644
index 00000000..9c1d1254
--- /dev/null
+++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/entity/ConfigRouteBase.java
@@ -0,0 +1,40 @@
+package com.gitee.sop.adminserver.entity;
+
+import lombok.Data;
+
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+
+/**
+ * 表名:config_route_base
+ * 备注:路由配置表
+ *
+ * @author tanghc
+ */
+@Table(name = "config_route_base")
+@Data
+public class ConfigRouteBase {
+ @Id
+ @Column(name = "id")
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ /** 数据库字段:id */
+ private Long id;
+
+ /** 路由id, 数据库字段:route_id */
+ private String routeId;
+
+ /** 状态,1:启用,2:禁用, 数据库字段:status */
+ private Byte status;
+
+ /** 数据库字段:gmt_create */
+ private Date gmtCreate;
+
+ /** 数据库字段:gmt_modified */
+ private Date gmtModified;
+}
diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/entity/ConfigRouteLimit.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/entity/ConfigRouteLimit.java
new file mode 100644
index 00000000..66d25175
--- /dev/null
+++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/entity/ConfigRouteLimit.java
@@ -0,0 +1,55 @@
+package com.gitee.sop.adminserver.entity;
+
+import lombok.Data;
+
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+
+/**
+ * 表名:config_route_limit
+ * 备注:路由限流配置
+ *
+ * @author tanghc
+ */
+@Table(name = "config_route_limit")
+@Data
+public class ConfigRouteLimit {
+ @Id
+ @Column(name = "id")
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ /** 数据库字段:id */
+ private Integer id;
+
+ /** 路由id, 数据库字段:route_id */
+ private String routeId;
+
+ /** 限流策略,1:漏桶策略,2:令牌桶策略, 数据库字段:type */
+ private Byte type;
+
+ /** 每秒可处理请求数, 数据库字段:exec_count_per_second */
+ private Integer execCountPerSecond;
+
+ /** 返回的错误码, 数据库字段:limit_code */
+ private String limitCode;
+
+ /** 返回的错误信息, 数据库字段:limit_msg */
+ private String limitMsg;
+
+ /** 令牌桶容量, 数据库字段:token_bucket_count */
+ private Integer tokenBucketCount;
+
+ /** 1:开启,0关闭, 数据库字段:limit_status */
+ private Byte limitStatus;
+
+ /** 数据库字段:gmt_create */
+ private Date gmtCreate;
+
+ /** 数据库字段:gmt_modified */
+ private Date gmtModified;
+}
diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/mapper/ConfigRouteBaseMapper.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/mapper/ConfigRouteBaseMapper.java
new file mode 100644
index 00000000..8d2d6d34
--- /dev/null
+++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/mapper/ConfigRouteBaseMapper.java
@@ -0,0 +1,12 @@
+package com.gitee.sop.adminserver.mapper;
+
+import com.gitee.fastmybatis.core.mapper.CrudMapper;
+
+import com.gitee.sop.adminserver.entity.ConfigRouteBase;
+
+
+/**
+ * @author tanghc
+ */
+public interface ConfigRouteBaseMapper extends CrudMapper {
+}
diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/mapper/ConfigRouteLimitMapper.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/mapper/ConfigRouteLimitMapper.java
new file mode 100644
index 00000000..38438296
--- /dev/null
+++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/mapper/ConfigRouteLimitMapper.java
@@ -0,0 +1,12 @@
+package com.gitee.sop.adminserver.mapper;
+
+import com.gitee.fastmybatis.core.mapper.CrudMapper;
+
+import com.gitee.sop.adminserver.entity.ConfigRouteLimit;
+
+
+/**
+ * @author tanghc
+ */
+public interface ConfigRouteLimitMapper extends CrudMapper {
+}
diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/ConfigRouteBaseService.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/ConfigRouteBaseService.java
new file mode 100644
index 00000000..f69256fc
--- /dev/null
+++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/ConfigRouteBaseService.java
@@ -0,0 +1,15 @@
+package com.gitee.sop.adminserver.service;
+
+import org.springframework.stereotype.Service;
+
+/**
+ * @author tanghc
+ */
+@Service
+public class ConfigRouteBaseService {
+
+ public void updateConfigRouteBase() {
+
+ }
+
+}
diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RouteConfigService.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RouteConfigService.java
new file mode 100644
index 00000000..8719938d
--- /dev/null
+++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RouteConfigService.java
@@ -0,0 +1,30 @@
+package com.gitee.sop.adminserver.service;
+
+import com.alibaba.fastjson.JSON;
+import com.gitee.sop.adminserver.bean.ChannelMsg;
+import com.gitee.sop.adminserver.bean.RouteConfigDto;
+import com.gitee.sop.adminserver.bean.ZookeeperContext;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author tanghc
+ */
+@Service
+@Slf4j
+public class RouteConfigService {
+
+ /**
+ * 发送路由配置消息
+ * @param routeConfigDto
+ * @throws Exception
+ */
+ public void sendRouteConfigMsg(RouteConfigDto routeConfigDto) throws Exception {
+ String configData = JSON.toJSONString(routeConfigDto);
+ ChannelMsg channelMsg = new ChannelMsg("update", configData);
+ String jsonData = JSON.toJSONString(channelMsg);
+ String path = ZookeeperContext.getRouteConfigChannelPath();
+ log.info("消息推送--路由配置(update), path:{}, data:{}", path, jsonData);
+ ZookeeperContext.createOrUpdateData(path, jsonData);
+ }
+}
diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RoutePermissionService.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RoutePermissionService.java
index 2e2e5373..3600a31f 100644
--- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RoutePermissionService.java
+++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RoutePermissionService.java
@@ -93,7 +93,7 @@ public class RoutePermissionService {
/**
* 推送所有路由权限到zookeeper
*/
- public void sendRoutePermissionReloadToZookeeper() throws Exception {
+ public void sendRoutePermissionReloadMsg() throws Exception {
ChannelMsg channelMsg = new ChannelMsg("reload", null);
String jsonData = JSON.toJSONString(channelMsg);
String path = ZookeeperContext.getIsvRoutePermissionChannelPath();
diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RouteService.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RouteService.java
new file mode 100644
index 00000000..4b48c084
--- /dev/null
+++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RouteService.java
@@ -0,0 +1,53 @@
+package com.gitee.sop.adminserver.service;
+
+import com.alibaba.fastjson.JSON;
+import com.gitee.sop.adminserver.api.service.param.RouteSearchParam;
+import com.gitee.sop.adminserver.bean.GatewayRouteDefinition;
+import com.gitee.sop.adminserver.bean.ZookeeperContext;
+import org.apache.commons.lang.StringUtils;
+import org.apache.curator.framework.recipes.cache.ChildData;
+import org.springframework.stereotype.Service;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Stream;
+
+import static java.util.stream.Collectors.toList;
+
+/**
+ * @author tanghc
+ */
+@Service
+public class RouteService {
+
+ public List getRouteDefinitionList(RouteSearchParam param) throws Exception {
+ if (StringUtils.isBlank(param.getServiceId())) {
+ return Collections.emptyList();
+ }
+
+ String searchPath = ZookeeperContext.getSopRouteRootPath() + "/" + param.getServiceId();
+
+ List childDataList = ZookeeperContext.getChildrenData(searchPath);
+
+ List routeDefinitionStream = childDataList.stream()
+ .map(childData -> {
+ String serviceNodeData = new String(childData.getData());
+ GatewayRouteDefinition routeDefinition = JSON.parseObject(serviceNodeData, GatewayRouteDefinition.class);
+ return routeDefinition;
+ })
+ .filter(gatewayRouteDefinition -> {
+ boolean isRoute = gatewayRouteDefinition.getOrder() != Integer.MIN_VALUE;
+ String id = param.getId();
+ if (StringUtils.isBlank(id)) {
+ return isRoute;
+ } else {
+ return isRoute && gatewayRouteDefinition.getId().contains(id);
+ }
+ })
+ .collect(toList())
+ ;
+
+ return routeDefinitionStream;
+ }
+
+}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/ApiConfig.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/ApiConfig.java
index 5fce9ba4..f9326a63 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/ApiConfig.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/ApiConfig.java
@@ -4,7 +4,9 @@ import com.gitee.sop.gatewaycommon.gateway.param.GatewayParamBuilder;
import com.gitee.sop.gatewaycommon.gateway.result.GatewayResult;
import com.gitee.sop.gatewaycommon.gateway.result.GatewayResultExecutor;
import com.gitee.sop.gatewaycommon.manager.DefaultIsvRoutePermissionManager;
+import com.gitee.sop.gatewaycommon.manager.DefaultRouteConfigManager;
import com.gitee.sop.gatewaycommon.manager.IsvRoutePermissionManager;
+import com.gitee.sop.gatewaycommon.manager.RouteConfigManager;
import com.gitee.sop.gatewaycommon.param.ParamBuilder;
import com.gitee.sop.gatewaycommon.result.ResultExecutor;
import com.gitee.sop.gatewaycommon.secret.CacheIsvManager;
@@ -94,6 +96,11 @@ public class ApiConfig {
*/
private IsvRoutePermissionManager isvRoutePermissionManager = new DefaultIsvRoutePermissionManager();
+ /**
+ * 路由配置管理
+ */
+ private RouteConfigManager routeConfigManager = new DefaultRouteConfigManager();
+
// -------- fields ---------
/**
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/BaseRouteDefinition.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/BaseRouteDefinition.java
index 389101c8..e46e6671 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/BaseRouteDefinition.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/BaseRouteDefinition.java
@@ -34,11 +34,6 @@ public class BaseRouteDefinition {
*/
private int ignoreValidate;
- /**
- * 状态,0:待审核,1:启用,2:禁用
- */
- private int status = 1;
-
/**
* 是否合并结果
*/
@@ -48,8 +43,4 @@ public class BaseRouteDefinition {
* 接口是否需要授权才能访问
*/
private int permission;
-
- public boolean enable() {
- return status == RouteStatus.ENABLE.getStatus();
- }
}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/RouteConfig.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/RouteConfig.java
new file mode 100644
index 00000000..0093daa9
--- /dev/null
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/RouteConfig.java
@@ -0,0 +1,46 @@
+package com.gitee.sop.gatewaycommon.bean;
+
+import lombok.Data;
+
+/**
+ * @author tanghc
+ */
+@Data
+public class RouteConfig {
+
+ public static final byte STATUS_ENABLE = 1;
+ public static final byte LIMIT_STATUS_CLOSE = 0;
+
+ private String routeId;
+
+ /** 限流策略,1:漏桶策略,2:令牌桶策略, 数据库字段:type */
+ private Byte type;
+
+ /** 每秒可处理请求数, 数据库字段:exec_count_per_second */
+ private Integer execCountPerSecond;
+
+ /** 返回的错误码, 数据库字段:limit_code */
+ private String limitCode;
+
+ /** 返回的错误信息, 数据库字段:limit_msg */
+ private String limitMsg;
+
+ /** 令牌桶容量, 数据库字段:token_bucket_count */
+ private Integer tokenBucketCount;
+
+ /** 限流开启状态,1:开启,0关闭, 数据库字段:limit_status */
+ private Byte limitStatus = LIMIT_STATUS_CLOSE;
+
+ /**
+ * 状态,0:待审核,1:启用,2:禁用
+ */
+ private Byte status = STATUS_ENABLE;
+
+ /**
+ * 是否启用
+ * @return
+ */
+ public boolean enable() {
+ return status == STATUS_ENABLE;
+ }
+}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/RouteConfigDto.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/RouteConfigDto.java
new file mode 100644
index 00000000..664bb478
--- /dev/null
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/RouteConfigDto.java
@@ -0,0 +1,37 @@
+package com.gitee.sop.gatewaycommon.bean;
+
+import lombok.Data;
+
+/**
+ * @author tanghc
+ */
+@Data
+public class RouteConfigDto {
+
+ private String routeId;
+
+ /** 限流策略,1:漏桶策略,2:令牌桶策略, 数据库字段:type */
+ private Byte type;
+
+ /** 每秒可处理请求数, 数据库字段:exec_count_per_second */
+ private Integer execCountPerSecond;
+
+ /** 返回的错误码, 数据库字段:limit_code */
+ private String limitCode;
+
+ /** 返回的错误信息, 数据库字段:limit_msg */
+ private String limitMsg;
+
+ /** 令牌桶容量, 数据库字段:token_bucket_count */
+ private Integer tokenBucketCount;
+
+ /** 限流开启状态,1:开启,0关闭, 数据库字段:limit_status */
+ private Byte limitStatus;
+
+ /**
+ * 状态,0:待审核,1:启用,2:禁用
+ */
+ private Byte status;
+
+
+}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/NameVersionRoutePredicateFactory.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/NameVersionRoutePredicateFactory.java
index cc6686cc..1ee16ce3 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/NameVersionRoutePredicateFactory.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/NameVersionRoutePredicateFactory.java
@@ -1,7 +1,10 @@
package com.gitee.sop.gatewaycommon.gateway.route;
+import com.gitee.sop.gatewaycommon.bean.ApiConfig;
+import com.gitee.sop.gatewaycommon.bean.RouteConfig;
import com.gitee.sop.gatewaycommon.bean.SopConstants;
import com.gitee.sop.gatewaycommon.bean.TargetRoute;
+import com.gitee.sop.gatewaycommon.manager.RouteConfigManager;
import com.gitee.sop.gatewaycommon.manager.RouteRepositoryContext;
import com.gitee.sop.gatewaycommon.param.ParamNames;
import com.gitee.sop.gatewaycommon.util.RequestUtil;
@@ -64,7 +67,9 @@ public class NameVersionRoutePredicateFactory extends AbstractRoutePredicateFact
boolean match = (name + version).equals(nameVersion);
if (match) {
TargetRoute targetRoute = RouteRepositoryContext.getRouteRepository().get(nameVersion);
- if (targetRoute != null && !targetRoute.getRouteDefinition().enable()) {
+ RouteConfigManager routeConfigManager = ApiConfig.getInstance().getRouteConfigManager();
+ RouteConfig routeConfig = routeConfigManager.get(nameVersion);
+ if (targetRoute != null && !routeConfig.enable()) {
return false;
}
}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/DefaultRouteConfigManager.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/DefaultRouteConfigManager.java
new file mode 100644
index 00000000..701c772e
--- /dev/null
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/DefaultRouteConfigManager.java
@@ -0,0 +1,49 @@
+package com.gitee.sop.gatewaycommon.manager;
+
+import com.gitee.sop.gatewaycommon.bean.RouteConfig;
+import com.gitee.sop.gatewaycommon.bean.RouteConfigDto;
+import com.gitee.sop.gatewaycommon.util.MyBeanUtil;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author tanghc
+ */
+public class DefaultRouteConfigManager implements RouteConfigManager {
+ /**
+ * key: routeId
+ */
+ protected static Map routeConfigMap = new ConcurrentHashMap<>(64);
+
+ private static RouteConfig DEFAULT_CONFIG;
+
+ public DefaultRouteConfigManager() {
+ DEFAULT_CONFIG = this.newRouteConfig();
+ }
+
+ @Override
+ public void load() {
+
+ }
+
+ @Override
+ public void update(RouteConfigDto routeConfigDto) {
+ String key = routeConfigDto.getRouteId();
+ RouteConfig routeConfig = routeConfigMap.get(key);
+ if (routeConfig == null) {
+ routeConfig = newRouteConfig();
+ routeConfigMap.put(key, routeConfig);
+ }
+ MyBeanUtil.copyPropertiesIgnoreNull(routeConfigDto, routeConfig);
+ }
+
+ protected RouteConfig newRouteConfig() {
+ return new RouteConfig();
+ }
+
+ @Override
+ public RouteConfig get(String routeId) {
+ return routeConfigMap.getOrDefault(routeId, DEFAULT_CONFIG);
+ }
+}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RouteConfigManager.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RouteConfigManager.java
new file mode 100644
index 00000000..67ace4df
--- /dev/null
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RouteConfigManager.java
@@ -0,0 +1,25 @@
+package com.gitee.sop.gatewaycommon.manager;
+
+import com.gitee.sop.gatewaycommon.bean.RouteConfig;
+import com.gitee.sop.gatewaycommon.bean.RouteConfigDto;
+
+/**
+ * 路由配置管理
+ * @author tanghc
+ */
+public interface RouteConfigManager {
+ void load();
+
+ /**
+ * 更新路由配置
+ * @param routeConfigDto
+ */
+ void update(RouteConfigDto routeConfigDto);
+
+ /**
+ * 获取路由配置
+ * @param routeId
+ * @return
+ */
+ RouteConfig get(String routeId);
+}
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
index a39e23ba..33a717f2 100644
--- 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
@@ -74,6 +74,10 @@ public class ZookeeperContext {
return SOP_MSG_CHANNEL_PATH + "/isv-route-permission";
}
+ public static String getRouteConfigChannelPath() {
+ return SOP_MSG_CHANNEL_PATH + "/route-conf";
+ }
+
public static CuratorFramework getClient() {
return client;
}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/message/ErrorEnum.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/message/ErrorEnum.java
index c9557854..6a20cfed 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/message/ErrorEnum.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/message/ErrorEnum.java
@@ -10,8 +10,11 @@ public enum ErrorEnum {
/** 服务暂不可用 */
ISP_UNKNOW_ERROR(Codes.CODE_UNKNOW, "isp.unknow-error"),
- /** */
+ /** 服务暂不可用 */
AOP_UNKNOW_ERROR(Codes.CODE_UNKNOW, "aop.unknow-error"),
+ /** 服务不可用,路由被禁用 */
+ ISP_API_DISABLED(Codes.CODE_UNKNOW, "isp.service-not-available"),
+
/** 无效的访问令牌 */
AOP_INVALID_AUTH_TOKEN(Codes.CODE_AUTH, "aop.invalid-auth-token"),
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/util/MyBeanUtil.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/util/MyBeanUtil.java
new file mode 100644
index 00000000..14fd3963
--- /dev/null
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/util/MyBeanUtil.java
@@ -0,0 +1,130 @@
+package com.gitee.sop.gatewaycommon.util;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.FatalBeanException;
+import org.springframework.util.Assert;
+
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 对象拷贝
+ *
+ * @author tanghc
+ */
+public class MyBeanUtil extends org.springframework.beans.BeanUtils {
+
+ /**
+ * 属性拷贝,第一个参数中的属性值拷贝到第二个参数中
+ * 注意:当第一个参数中的属性有null值时,不会拷贝进去
+ *
+ * @param source 源对象
+ * @param target 目标对象
+ * @throws BeansException
+ */
+ public static void copyPropertiesIgnoreNull(Object source, Object target)
+ throws BeansException {
+ Assert.notNull(source, "Source must not be null");
+ Assert.notNull(target, "Target must not be null");
+ Class> actualEditable = target.getClass();
+ PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
+ for (PropertyDescriptor targetPd : targetPds) {
+ Method writeMethod = targetPd.getWriteMethod();
+ if (writeMethod != null) {
+ PropertyDescriptor sourcePd = getPropertyDescriptor(
+ source.getClass(), targetPd.getName());
+ if (sourcePd != null && sourcePd.getReadMethod() != null) {
+ try {
+ Method readMethod = sourcePd.getReadMethod();
+ if (!Modifier.isPublic(readMethod.getDeclaringClass()
+ .getModifiers())) {
+ readMethod.setAccessible(true);
+ }
+ Object value = readMethod.invoke(source);
+ // 这里判断value是否为空 当然这里也能进行一些特殊要求的处理
+ // 例如绑定时格式转换等等
+ if (value != null) {
+ if (!Modifier.isPublic(writeMethod
+ .getDeclaringClass().getModifiers())) {
+ writeMethod.setAccessible(true);
+ }
+ writeMethod.invoke(target, value);
+ }
+ } catch (Throwable ex) {
+ throw new FatalBeanException(
+ "Could not copy properties from source to target field name mismatch:" + targetPd.getName(),
+ ex);
+ }
+ }
+ }
+ }
+ }
+
+
+ /**
+ * 属性拷贝,把map中的值拷贝到target中去
+ *
+ * @param map map对象
+ * @param target 目标对象
+ */
+ public static void copyPropertiesForMap(Map map, Object target) {
+ Assert.notNull(map, "map must not be null");
+ Assert.notNull(target, "Target must not be null");
+ Object pojo = mapToPojo(map, target.getClass());
+ copyProperties(pojo, target);
+ }
+
+ /**
+ * 将实体对象转换成Map
+ *
+ * @param pojo 实体类
+ * @return 返回map
+ */
+ public static Map pojoToMap(Object pojo) {
+ if (pojo == null) {
+ return Collections.emptyMap();
+ }
+ String json = JSON.toJSONString(pojo);
+ return JSON.parseObject(json);
+ }
+
+
+ /**
+ * 将map对象转换成普通类
+ *
+ * @param 普通类类型
+ * @param map map对象
+ * @param pojoClass 普通类
+ * @return 返回普通类
+ */
+ public static T mapToPojo(Map map, Class pojoClass) {
+ return new JSONObject(map).toJavaObject(pojoClass);
+ }
+
+ /**
+ * map集合转换成对象集合
+ *
+ * @param 普通类类型
+ * @param list map集合
+ * @param pojoClass 待转换的对象类型
+ * @return 返回对象集合
+ */
+ public static List mapListToObjList(List