mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-08-11 21:57:56 +08:00
1.3.0
This commit is contained in:
@@ -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 ---------
|
||||
|
||||
/**
|
||||
|
@@ -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();
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
|
||||
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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<String, RouteConfig> 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);
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -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;
|
||||
}
|
||||
|
@@ -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"),
|
||||
|
@@ -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 {
|
||||
|
||||
/**
|
||||
* 属性拷贝,第一个参数中的属性值拷贝到第二个参数中<br>
|
||||
* 注意:当第一个参数中的属性有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<String, Object> 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<String, Object> pojoToMap(Object pojo) {
|
||||
if (pojo == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
String json = JSON.toJSONString(pojo);
|
||||
return JSON.parseObject(json);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将map对象转换成普通类
|
||||
*
|
||||
* @param <T> 普通类类型
|
||||
* @param map map对象
|
||||
* @param pojoClass 普通类
|
||||
* @return 返回普通类
|
||||
*/
|
||||
public static <T> T mapToPojo(Map<String, Object> map, Class<T> pojoClass) {
|
||||
return new JSONObject(map).toJavaObject(pojoClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* map集合转换成对象集合
|
||||
*
|
||||
* @param <T> 普通类类型
|
||||
* @param list map集合
|
||||
* @param pojoClass 待转换的对象类型
|
||||
* @return 返回对象集合
|
||||
*/
|
||||
public static <T> List<T> mapListToObjList(List<Map<String, Object>> list, Class<T> pojoClass) {
|
||||
if (list == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<T> retList = new ArrayList<>(list.size());
|
||||
for (Map<String, Object> map : list) {
|
||||
retList.add(mapToPojo(map, pojoClass));
|
||||
}
|
||||
return retList;
|
||||
}
|
||||
|
||||
}
|
@@ -1,5 +1,8 @@
|
||||
package com.gitee.sop.gatewaycommon.zuul.route;
|
||||
|
||||
import com.gitee.sop.gatewaycommon.bean.ApiConfig;
|
||||
import com.gitee.sop.gatewaycommon.bean.RouteConfig;
|
||||
import com.gitee.sop.gatewaycommon.manager.RouteConfigManager;
|
||||
import com.gitee.sop.gatewaycommon.message.ErrorEnum;
|
||||
import com.gitee.sop.gatewaycommon.param.ApiParam;
|
||||
import com.gitee.sop.gatewaycommon.zuul.ZuulContext;
|
||||
@@ -51,8 +54,10 @@ public class SopRouteLocator implements RouteLocator, Ordered {
|
||||
return null;
|
||||
}
|
||||
// 路由是否启用
|
||||
if (!zuulTargetRoute.getRouteDefinition().enable()) {
|
||||
throw ErrorEnum.ISV_INVALID_METHOD.getErrorMeta().getException();
|
||||
RouteConfigManager routeConfigManager = ApiConfig.getInstance().getRouteConfigManager();
|
||||
RouteConfig routeConfig = routeConfigManager.get(zuulTargetRoute.getRouteDefinition().getId());
|
||||
if (!routeConfig.enable()) {
|
||||
throw ErrorEnum.ISP_API_DISABLED.getErrorMeta().getException();
|
||||
}
|
||||
return zuulTargetRoute.getTargetRouteDefinition();
|
||||
}
|
||||
|
@@ -5,6 +5,7 @@ open.error_10000=Success
|
||||
open.error_20000=Service is temporarily unavailable
|
||||
open.error_20000_isp.unknow-error=Service is temporarily unavailable
|
||||
open.error_20000_aop.unknow-error=Service is temporarily unavailable
|
||||
open.error_20000_isp.service-not-available=Service is temporarily unavailable
|
||||
|
||||
open.error_20001=Insufficient authorization authority
|
||||
open.error_20001_aop.invalid-auth-token=Invalid access token
|
||||
|
@@ -3,6 +3,7 @@
|
||||
#open.error_20000=服务不可用
|
||||
#open.error_20000_isp.unknow-error=服务暂不可用
|
||||
#open.error_20000_aop.unknow-error=服务暂不可用
|
||||
#open.error_20000_isp.service-not-available=服务暂不可用
|
||||
#
|
||||
#open.error_20001=授权权限不足
|
||||
#open.error_20001_aop.invalid-auth-token=无效的访问令牌
|
||||
@@ -59,6 +60,7 @@ open.error_10000=Success
|
||||
open.error_20000=\u670d\u52a1\u4e0d\u53ef\u7528
|
||||
open.error_20000_isp.unknow-error=\u670d\u52a1\u6682\u4e0d\u53ef\u7528
|
||||
open.error_20000_aop.unknow-error=\u670d\u52a1\u6682\u4e0d\u53ef\u7528
|
||||
open.error_20000_isp.service-not-available=\u670d\u52a1\u6682\u4e0d\u53ef\u7528
|
||||
|
||||
open.error_20001=\u6388\u6743\u6743\u9650\u4e0d\u8db3
|
||||
open.error_20001_aop.invalid-auth-token=\u65e0\u6548\u7684\u8bbf\u95ee\u4ee4\u724c
|
||||
|
Reference in New Issue
Block a user