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; 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.RouteDefinition;
import com.gitee.sop.gatewaycommon.bean.ServiceRouteInfo; import com.gitee.sop.gatewaycommon.bean.ServiceRouteInfo;
import com.gitee.sop.gatewaycommon.manager.BaseRouteCache; 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 org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import java.net.URI; import java.net.URI;
import java.util.ArrayList;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
/** /**
* @author tanghc * @author tanghc
@ -25,45 +23,37 @@ public class GatewayRouteCache extends BaseRouteCache<GatewayTargetRoute> {
} }
@Override @Override
protected GatewayTargetRoute buildRouteDefinition(ServiceRouteInfo serviceRouteInfo, RouteDefinition gatewayRouteDefinition) { protected GatewayTargetRoute buildTargetRoute(ServiceRouteInfo serviceRouteInfo, RouteDefinition routeDefinition) {
org.springframework.cloud.gateway.route.RouteDefinition routeDefinition = new org.springframework.cloud.gateway.route.RouteDefinition(); org.springframework.cloud.gateway.route.RouteDefinition targetRoute = new org.springframework.cloud.gateway.route.RouteDefinition();
routeDefinition.setId(gatewayRouteDefinition.getId()); targetRoute.setId(routeDefinition.getId());
routeDefinition.setUri(URI.create(gatewayRouteDefinition.getUri() + "#" + gatewayRouteDefinition.getPath())); targetRoute.setUri(URI.create(routeDefinition.getUri() + "#" + routeDefinition.getPath()));
routeDefinition.setOrder(gatewayRouteDefinition.getOrder()); targetRoute.setOrder(routeDefinition.getOrder());
List<FilterDefinition> filterDefinitionList = new ArrayList<>(gatewayRouteDefinition.getFilters().size()); // 添加过滤器
LinkedList<PredicateDefinition> predicateDefinitionList = new LinkedList<>(); List<FilterDefinition> filterDefinitionList = routeDefinition.getFilters()
for (GatewayFilterDefinition filter : gatewayRouteDefinition.getFilters()) { .stream()
.map(filter -> {
FilterDefinition filterDefinition = new FilterDefinition(); FilterDefinition filterDefinition = new FilterDefinition();
BeanUtils.copyProperties(filter, 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(); PredicateDefinition predicateDefinition = new PredicateDefinition();
BeanUtils.copyProperties(predicate, predicateDefinition); BeanUtils.copyProperties(predicate, predicateDefinition);
predicateDefinitionList.add(predicateDefinition); return predicateDefinition;
} })
this.addPredicate(predicateDefinitionList, "NameVersion", gatewayRouteDefinition.getId()); .collect(Collectors.toCollection(LinkedList::new));
this.addPredicate(predicateDefinitionList, "ReadBody", ""); // 添加下面两个自定义的断言到顶部
routeDefinition.setFilters(filterDefinitionList); predicateDefinitionList.addFirst(new PredicateDefinition("NameVersion=" + routeDefinition.getId()));
routeDefinition.setPredicates(predicateDefinitionList); predicateDefinitionList.addFirst(new PredicateDefinition("ReadBody="));
return new GatewayTargetRoute(serviceRouteInfo, gatewayRouteDefinition, routeDefinition);
}
/** targetRoute.setFilters(filterDefinitionList);
* 添加断言 targetRoute.setPredicates(predicateDefinitionList);
* return new GatewayTargetRoute(serviceRouteInfo, routeDefinition, targetRoute);
* @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));
} }
} }

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

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

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

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

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

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

@ -2,7 +2,6 @@ package com.gitee.sop.servercommon.manager;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.gitee.sop.servercommon.bean.ServiceApiInfo; 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.RouteDefinition;
import com.gitee.sop.servercommon.route.ServiceRouteInfo; import com.gitee.sop.servercommon.route.ServiceRouteInfo;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -13,7 +12,6 @@ import org.springframework.util.StringUtils;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -33,13 +31,7 @@ public class ServiceRouteInfoBuilder {
private static final String DEFAULT_CONTEXT_PATH = "/"; private static final String DEFAULT_CONTEXT_PATH = "/";
/** private static ServiceApiInfo.ApiMeta FIRST_API_META = new ServiceApiInfo.ApiMeta("_first_route_", "/", "1.0.0");
* 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 Environment environment;
@ -59,8 +51,9 @@ public class ServiceRouteInfoBuilder {
*/ */
protected ServiceRouteInfo buildServiceGatewayInfo(ServiceApiInfo serviceApiInfo) { protected ServiceRouteInfo buildServiceGatewayInfo(ServiceApiInfo serviceApiInfo) {
List<ServiceApiInfo.ApiMeta> apis = serviceApiInfo.getApis(); List<ServiceApiInfo.ApiMeta> apis = serviceApiInfo.getApis();
List<RouteDefinition> routeDefinitionList = new ArrayList<>(apis.size()); List<RouteDefinition> routeDefinitionList = new ArrayList<>(apis.size() + 1);
routeDefinitionList.add(this.buildReadBodyRouteDefinition(serviceApiInfo)); // 在第一个位置放一个没用的路由,SpringCloudGateway会从第二个路由开始找,原因不详
routeDefinitionList.add(this.getFirstRoute(serviceApiInfo));
for (ServiceApiInfo.ApiMeta apiMeta : apis) { for (ServiceApiInfo.ApiMeta apiMeta : apis) {
RouteDefinition gatewayRouteDefinition = this.buildGatewayRouteDefinition(serviceApiInfo, apiMeta); RouteDefinition gatewayRouteDefinition = this.buildGatewayRouteDefinition(serviceApiInfo, apiMeta);
routeDefinitionList.add(gatewayRouteDefinition); routeDefinitionList.add(gatewayRouteDefinition);
@ -73,6 +66,17 @@ public class ServiceRouteInfoBuilder {
return serviceRouteInfo; 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 * 构建路由id MD5
* *
@ -89,43 +93,19 @@ public class ServiceRouteInfoBuilder {
} }
protected RouteDefinition buildGatewayRouteDefinition(ServiceApiInfo serviceApiInfo, ServiceApiInfo.ApiMeta apiMeta) { protected RouteDefinition buildGatewayRouteDefinition(ServiceApiInfo serviceApiInfo, ServiceApiInfo.ApiMeta apiMeta) {
RouteDefinition gatewayRouteDefinition = new RouteDefinition(); RouteDefinition routeDefinition = new RouteDefinition();
// 唯一id规则:接口名 + 版本号 // 唯一id规则:接口名 + 版本号
String routeId = apiMeta.fetchNameVersion(); String routeId = apiMeta.fetchNameVersion();
this.checkPath(routeId, "接口定义(" + routeId + ")不能有斜杠字符'/'"); this.checkPath(routeId, "接口定义(" + routeId + ")不能有斜杠字符'/'");
BeanUtils.copyProperties(apiMeta, gatewayRouteDefinition); BeanUtils.copyProperties(apiMeta, routeDefinition);
gatewayRouteDefinition.setId(routeId); routeDefinition.setId(routeId);
gatewayRouteDefinition.setFilters(Collections.emptyList()); routeDefinition.setFilters(Collections.emptyList());
gatewayRouteDefinition.setPredicates(this.buildPredicates(apiMeta)); routeDefinition.setPredicates(Collections.emptyList());
String uri = this.buildUri(serviceApiInfo, apiMeta); String uri = this.buildUri(serviceApiInfo, apiMeta);
String path = this.buildServletPath(serviceApiInfo, apiMeta); String path = this.buildServletPath(serviceApiInfo, apiMeta);
gatewayRouteDefinition.setUri(uri); routeDefinition.setUri(uri);
gatewayRouteDefinition.setPath(path); routeDefinition.setPath(path);
return gatewayRouteDefinition; return routeDefinition;
}
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;
} }
protected String buildUri(ServiceApiInfo serviceApiInfo, ServiceApiInfo.ApiMeta apiMeta) { protected String buildUri(ServiceApiInfo serviceApiInfo, ServiceApiInfo.ApiMeta apiMeta) {

@ -2,7 +2,6 @@ package com.gitee.sop.servercommon.route;
import lombok.Data; import lombok.Data;
import java.util.ArrayList;
import java.util.List; 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 * 路由规则转发的目标uri

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

@ -126,6 +126,45 @@ biz_content String 是 请求参数的集合,最大长度不限,除公共
bizContent.put("name", "葫芦娃"); bizContent.put("name", "葫芦娃");
// bizContent.put("name", "葫芦娃1234567890葫芦娃1234567890"); // 超出长度 // 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)); params.put("biz_content", JSON.toJSONString(bizContent));
System.out.println("----------- 请求信息 -----------"); System.out.println("----------- 请求信息 -----------");

Loading…
Cancel
Save