pull/1/head
tanghc 5 years ago
parent a4f7527716
commit bdb4446758
  1. 64
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayRouteCache.java
  2. 7
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayRouteRepository.java
  3. 3
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/NameVersionRoutePredicateFactory.java
  4. 4
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/ReadBodyRoutePredicateFactory.java
  5. 12
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/BaseRouteCache.java
  6. 6
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ServiceRoutesLoader.java
  7. 2
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/ZuulRouteCache.java
  8. 66
      sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceRouteInfoBuilder.java
  9. 5
      sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/route/RouteDefinition.java
  10. 2
      sop-gateway/src/main/resources/application-dev.properties
  11. 39
      sop-test/src/test/java/com/gitee/sop/test/SpringCloudGatewayClientPostTest.java

@ -1,7 +1,5 @@
package com.gitee.sop.gatewaycommon.gateway.route;
import com.gitee.sop.gatewaycommon.bean.GatewayFilterDefinition;
import com.gitee.sop.gatewaycommon.bean.GatewayPredicateDefinition;
import com.gitee.sop.gatewaycommon.bean.RouteDefinition;
import com.gitee.sop.gatewaycommon.bean.ServiceRouteInfo;
import com.gitee.sop.gatewaycommon.manager.BaseRouteCache;
@ -11,9 +9,9 @@ import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import java.net.URI;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author tanghc
@ -25,45 +23,37 @@ public class GatewayRouteCache extends BaseRouteCache<GatewayTargetRoute> {
}
@Override
protected GatewayTargetRoute buildRouteDefinition(ServiceRouteInfo serviceRouteInfo, RouteDefinition gatewayRouteDefinition) {
org.springframework.cloud.gateway.route.RouteDefinition routeDefinition = new org.springframework.cloud.gateway.route.RouteDefinition();
routeDefinition.setId(gatewayRouteDefinition.getId());
routeDefinition.setUri(URI.create(gatewayRouteDefinition.getUri() + "#" + gatewayRouteDefinition.getPath()));
routeDefinition.setOrder(gatewayRouteDefinition.getOrder());
List<FilterDefinition> filterDefinitionList = new ArrayList<>(gatewayRouteDefinition.getFilters().size());
LinkedList<PredicateDefinition> predicateDefinitionList = new LinkedList<>();
for (GatewayFilterDefinition filter : gatewayRouteDefinition.getFilters()) {
protected GatewayTargetRoute buildTargetRoute(ServiceRouteInfo serviceRouteInfo, RouteDefinition routeDefinition) {
org.springframework.cloud.gateway.route.RouteDefinition targetRoute = new org.springframework.cloud.gateway.route.RouteDefinition();
targetRoute.setId(routeDefinition.getId());
targetRoute.setUri(URI.create(routeDefinition.getUri() + "#" + routeDefinition.getPath()));
targetRoute.setOrder(routeDefinition.getOrder());
// 添加过滤器
List<FilterDefinition> filterDefinitionList = routeDefinition.getFilters()
.stream()
.map(filter -> {
FilterDefinition filterDefinition = new FilterDefinition();
BeanUtils.copyProperties(filter, filterDefinition);
filterDefinitionList.add(filterDefinition);
}
return filterDefinition;
})
.collect(Collectors.toList());
for (GatewayPredicateDefinition predicate : gatewayRouteDefinition.getPredicates()) {
LinkedList<PredicateDefinition> predicateDefinitionList = routeDefinition.getPredicates()
.stream()
.map(predicate -> {
PredicateDefinition predicateDefinition = new PredicateDefinition();
BeanUtils.copyProperties(predicate, predicateDefinition);
predicateDefinitionList.add(predicateDefinition);
}
this.addPredicate(predicateDefinitionList, "NameVersion", gatewayRouteDefinition.getId());
this.addPredicate(predicateDefinitionList, "ReadBody", "");
routeDefinition.setFilters(filterDefinitionList);
routeDefinition.setPredicates(predicateDefinitionList);
return new GatewayTargetRoute(serviceRouteInfo, gatewayRouteDefinition, routeDefinition);
}
return predicateDefinition;
})
.collect(Collectors.toCollection(LinkedList::new));
// 添加下面两个自定义的断言到顶部
predicateDefinitionList.addFirst(new PredicateDefinition("NameVersion=" + routeDefinition.getId()));
predicateDefinitionList.addFirst(new PredicateDefinition("ReadBody="));
/**
* 添加断言
*
* @param predicateDefinitionList
* @param name 断言名称
* @param args 断言参数
*/
protected void addPredicate(LinkedList<PredicateDefinition> predicateDefinitionList, String name, String args) {
for (PredicateDefinition predicateDefinition : predicateDefinitionList) {
// 如果已经存在,直接返回
if (predicateDefinition.getName().equals(name)) {
return;
}
}
predicateDefinitionList.addFirst(new PredicateDefinition(name + "=" + args));
targetRoute.setFilters(filterDefinitionList);
targetRoute.setPredicates(predicateDefinitionList);
return new GatewayTargetRoute(serviceRouteInfo, routeDefinition, targetRoute);
}
}

@ -6,7 +6,6 @@ import com.gitee.sop.gatewaycommon.manager.RouteRepository;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.gateway.event.PredicateArgsEvent;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
@ -40,7 +39,6 @@ public class GatewayRouteRepository implements ApplicationEventPublisherAware,
public Flux<org.springframework.cloud.gateway.route.RouteDefinition> getRouteDefinitions() {
List<org.springframework.cloud.gateway.route.RouteDefinition> list = routes.values().parallelStream()
.map(TargetRoute::getTargetRouteDefinition)
.filter(routeDefinition -> !routeDefinition.getId().contains("_first.route_"))
.collect(Collectors.toList());
return Flux.fromIterable(list);
}
@ -76,9 +74,8 @@ public class GatewayRouteRepository implements ApplicationEventPublisherAware,
*/
@Override
public String add(GatewayTargetRoute targetRoute) {
RouteDefinition baseRouteDefinition = targetRoute.getRouteDefinition();
routes.put(baseRouteDefinition.getId(), targetRoute);
this.publisher.publishEvent(new RefreshRoutesEvent(this));
RouteDefinition routeDefinition = targetRoute.getRouteDefinition();
routes.put(routeDefinition.getId(), targetRoute);
return "success";
}

@ -17,6 +17,9 @@ import java.util.function.Predicate;
/**
* 此断言决定执行哪个路由
*
* 使用地方
* @see com.gitee.sop.gatewaycommon.gateway.route.GatewayRouteCache
*
* @author tanghc
*/
@Slf4j

@ -36,6 +36,10 @@ import static org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilt
*
* @see org.springframework.cloud.gateway.handler.predicate.ReadBodyPredicateFactory
* 详见https://blog.51cto.com/thinklili/2329184
*
* 使用地方
* @see com.gitee.sop.gatewaycommon.gateway.route.GatewayRouteCache
*
* @author tanghc
*/
public class ReadBodyRoutePredicateFactory extends AbstractRoutePredicateFactory<ReadBodyRoutePredicateFactory.Config> {

@ -1,5 +1,6 @@
package com.gitee.sop.gatewaycommon.manager;
import com.alibaba.fastjson.JSON;
import com.gitee.sop.gatewaycommon.bean.RouteDefinition;
import com.gitee.sop.gatewaycommon.bean.ServiceRouteInfo;
import com.gitee.sop.gatewaycommon.bean.TargetRoute;
@ -31,7 +32,7 @@ public abstract class BaseRouteCache<T extends TargetRoute> implements RouteLoad
* @param gatewayRouteDefinition 路由对象
* @return 返回目标路由对象
*/
protected abstract T buildRouteDefinition(ServiceRouteInfo serviceRouteInfo, RouteDefinition gatewayRouteDefinition);
protected abstract T buildTargetRoute(ServiceRouteInfo serviceRouteInfo, RouteDefinition gatewayRouteDefinition);
public BaseRouteCache(RouteRepository<T> routeRepository) {
this.routeRepository = routeRepository;
@ -48,9 +49,12 @@ public abstract class BaseRouteCache<T extends TargetRoute> implements RouteLoad
}
serviceIdMd5Map.put(serviceId, newMd5);
List<RouteDefinition> routeDefinitionList = serviceRouteInfo.getRouteDefinitionList();
for (RouteDefinition gatewayRouteDefinition : routeDefinitionList) {
T routeDefinition = this.buildRouteDefinition(serviceRouteInfo, gatewayRouteDefinition);
routeRepository.add(routeDefinition);
for (RouteDefinition routeDefinition : routeDefinitionList) {
T targetRoute = this.buildTargetRoute(serviceRouteInfo, routeDefinition);
routeRepository.add(targetRoute);
if (log.isDebugEnabled()) {
log.debug("新增路由:{}", JSON.toJSONString(routeDefinition));
}
}
callback.accept(null);
} catch (Exception e) {

@ -41,12 +41,6 @@ public class ServiceRoutesLoader<T extends TargetRoute> {
@Autowired
private NacosDiscoveryProperties nacosDiscoveryProperties;
// @NacosInjected
// private NamingService namingService;
// @Autowired
// private NacosConfigProperties nacosConfigProperties;
@NacosInjected
private ConfigService configService;

@ -20,7 +20,7 @@ public class ZuulRouteCache extends BaseRouteCache<ZuulTargetRoute> {
}
@Override
protected ZuulTargetRoute buildRouteDefinition(ServiceRouteInfo serviceRouteInfo, RouteDefinition gatewayRouteDefinition) {
protected ZuulTargetRoute buildTargetRoute(ServiceRouteInfo serviceRouteInfo, RouteDefinition gatewayRouteDefinition) {
Route route = new Route(
gatewayRouteDefinition.getId()
, gatewayRouteDefinition.getPath()

@ -2,7 +2,6 @@ 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.RouteDefinition;
import com.gitee.sop.servercommon.route.ServiceRouteInfo;
import lombok.extern.slf4j.Slf4j;
@ -13,7 +12,6 @@ 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;
@ -33,13 +31,7 @@ public class ServiceRouteInfoBuilder {
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 static ServiceApiInfo.ApiMeta FIRST_API_META = new ServiceApiInfo.ApiMeta("_first_route_", "/", "1.0.0");
private Environment environment;
@ -59,8 +51,9 @@ public class ServiceRouteInfoBuilder {
*/
protected ServiceRouteInfo buildServiceGatewayInfo(ServiceApiInfo serviceApiInfo) {
List<ServiceApiInfo.ApiMeta> apis = serviceApiInfo.getApis();
List<RouteDefinition> routeDefinitionList = new ArrayList<>(apis.size());
routeDefinitionList.add(this.buildReadBodyRouteDefinition(serviceApiInfo));
List<RouteDefinition> routeDefinitionList = new ArrayList<>(apis.size() + 1);
// 在第一个位置放一个没用的路由,SpringCloudGateway会从第二个路由开始找,原因不详
routeDefinitionList.add(this.getFirstRoute(serviceApiInfo));
for (ServiceApiInfo.ApiMeta apiMeta : apis) {
RouteDefinition gatewayRouteDefinition = this.buildGatewayRouteDefinition(serviceApiInfo, apiMeta);
routeDefinitionList.add(gatewayRouteDefinition);
@ -73,6 +66,17 @@ public class ServiceRouteInfoBuilder {
return serviceRouteInfo;
}
/**
* 添加com.gitee.sop.gatewaycommon.routeDefinition.ReadBodyRoutePredicateFactory,解决form表单获取不到问题
*
* @return 返回路由定义
*/
protected RouteDefinition getFirstRoute(ServiceApiInfo serviceApiInfo) {
RouteDefinition firstRoute = this.buildGatewayRouteDefinition(serviceApiInfo, FIRST_API_META);
firstRoute.setOrder(Integer.MIN_VALUE);
return firstRoute;
}
/**
* 构建路由id MD5
*
@ -89,43 +93,19 @@ public class ServiceRouteInfoBuilder {
}
protected RouteDefinition buildGatewayRouteDefinition(ServiceApiInfo serviceApiInfo, ServiceApiInfo.ApiMeta apiMeta) {
RouteDefinition gatewayRouteDefinition = new RouteDefinition();
RouteDefinition routeDefinition = new RouteDefinition();
// 唯一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));
BeanUtils.copyProperties(apiMeta, routeDefinition);
routeDefinition.setId(routeId);
routeDefinition.setFilters(Collections.emptyList());
routeDefinition.setPredicates(Collections.emptyList());
String uri = this.buildUri(serviceApiInfo, apiMeta);
String path = this.buildServletPath(serviceApiInfo, apiMeta);
gatewayRouteDefinition.setUri(uri);
gatewayRouteDefinition.setPath(path);
return gatewayRouteDefinition;
}
protected List<GatewayPredicateDefinition> 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 RouteDefinition buildReadBodyRouteDefinition(ServiceApiInfo serviceApiInfo) {
RouteDefinition readBodyRouteDefinition = this.buildGatewayRouteDefinition(serviceApiInfo, FIRST_API_META);
readBodyRouteDefinition.setOrder(Integer.MIN_VALUE);
readBodyRouteDefinition.setPredicates(this.buildPredicates(FIRST_API_META));
return readBodyRouteDefinition;
routeDefinition.setUri(uri);
routeDefinition.setPath(path);
return routeDefinition;
}
protected String buildUri(ServiceApiInfo serviceApiInfo, ServiceApiInfo.ApiMeta apiMeta) {

@ -2,7 +2,6 @@ package com.gitee.sop.servercommon.route;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
@ -28,12 +27,12 @@ public class RouteDefinition {
/**
* 路由断言集合配置
*/
private List<GatewayPredicateDefinition> predicates = new ArrayList<>();
private List<GatewayPredicateDefinition> predicates;
/**
* 路由过滤器集合配置
*/
private List<GatewayFilterDefinition> filters = new ArrayList<>();
private List<GatewayFilterDefinition> filters;
/**
* 路由规则转发的目标uri

@ -57,3 +57,5 @@ spring.servlet.multipart.max-request-size=20MB
spring.zipkin.base-url=${zipkin.url}
# 设置sleuth收集信息的比率,默认0.1,最大是1,数字越大越耗性能
spring.sleuth.sampler.probability=1
logging.level.com.gitee=debug

@ -126,6 +126,45 @@ biz_content String 是 请求参数的集合,最大长度不限,除公共
bizContent.put("name", "葫芦娃");
// bizContent.put("name", "葫芦娃1234567890葫芦娃1234567890"); // 超出长度
params.put("biz_content", JSON.toJSONString(bizContent));
System.out.println("----------- 请求信息 -----------");
System.out.println("请求参数:" + buildParamQuery(params));
System.out.println("商户秘钥:" + privateKey);
String content = AlipaySignature.getSignContent(params);
System.out.println("待签名内容:" + content);
String sign = AlipaySignature.rsa256Sign(content, privateKey, "utf-8");
System.out.println("签名(sign):" + sign);
params.put("sign", sign);
System.out.println("----------- 返回结果 -----------");
String responseData = post(url, params);// 发送请求
System.out.println(responseData);
}
public void testPost2() throws Exception {
// 公共请求参数
Map<String, String> params = new HashMap<String, String>();
params.put("app_id", appId);
params.put("method", "alipay.category.get");
params.put("format", "json");
params.put("charset", "utf-8");
params.put("sign_type", "RSA2");
params.put("timestamp", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
params.put("version", "1.0");
// 业务参数
Map<String, Object> bizContent = new HashMap<>();
bizContent.put("categoryName", "啊啊啊");
Map<String, String> storyParam = new HashMap<>();
storyParam.put("id", "1");
storyParam.put("name", "葫芦娃啊啊啊");
bizContent.put("storyParam", storyParam);
params.put("biz_content", JSON.toJSONString(bizContent));
System.out.println("----------- 请求信息 -----------");

Loading…
Cancel
Save