2

我正在尝试将一组广泛的路由配置转换为 Spring Cloud Gateway Yaml DSL。

我遇到的一个问题是(非常常见的情况)多条路径应该映射到同一条路径。也就是说,任何与 、 或 匹配的传入 URL/abc/**都应/def/**路由/ghi/**到某个 uri http://example.org(并应用相同的过滤器集等)。

在 Fluent 基于 Java 的路由方法中,这可以通过以下.or().方法实现,例如:r.path("/abc/**").or().path("/def/**").or().path("/fhi/**")...

如何通过基于 YAML 的路由配置来实现相同的功能?

编辑:我在文档中看到: https ://cloud.spring.io/spring-cloud-gateway/single/spring-cloud-gateway.html#gateway-request-predicates-factories

“多个路由谓词工厂可以组合并通过逻辑组合and

是否有另一种方法可以通过 Yaml 实现路径谓词的 OR-ing 而无需声明多个路由?可以覆盖某些东西来支持这一点吗?

4

2 回答 2

3

你可能已经得到了答案。但是为了记录,我想说您可以为谓词添加多个路径,如下所示:

spring:
  cloud:
    gateway:
      routes:
        - id: instructors_route
          uri: lb://INSTRUCTOR-SERVICE/
          predicates:
            - Path=/api/v1/instructors**,/api/v1/countries**
于 2020-05-30T20:15:07.367 回答
0

我找到了处理谓词组合的方法:

RouteDefinitionRouteLocator.java: combinePredicates

private AsyncPredicate<ServerWebExchange> combinePredicates(RouteDefinition routeDefinition) {
    List<PredicateDefinition> predicates = routeDefinition.getPredicates();
    AsyncPredicate<ServerWebExchange> predicate = lookup(routeDefinition, predicates.get(0));

    for (PredicateDefinition andPredicate : predicates.subList(1, predicates.size())) {
        AsyncPredicate<ServerWebExchange> found = lookup(routeDefinition, andPredicate);
        predicate = predicate.and(found);
    }

    return predicate;
}

由于它是一个私有方法,为了用执行谓词的逻辑分离(“OR-ing”)的Path谓词组合逻辑覆盖这个逻辑,扩展类RouteDefinitionRouteLocator必须重新定义所有导致最终调用combinePredicates(这不是最灵活的路线)。但是,我能够通过重新实现这样的方法来实现所需的功能:

private AsyncPredicate<ServerWebExchange> combinePredicates(RouteDefinition routeDefinition) {
    //filter out "Path" predicates and place in separate list
    List<PredicateDefinition> predicates = routeDefinition.getPredicates();
    List<PredicateDefinition> pathPredicates = new ArrayList();
    for(PredicateDefinition predicate : predicates){
        if (PATH_PREDICATE_NAME.equals(predicate.getName())) {
            pathPredicates.add(predicate);
        }
    }
    predicates.removeAll(pathPredicates);

    //create an uber predicate out of the "Path" predicates by combining them w/ `or`
    AsyncPredicate<ServerWebExchange> pathPredicate = null;
    if(pathPredicates.size()>0){
        pathPredicate = lookup(routeDefinition, pathPredicates.get(0));
        for (PredicateDefinition andPredicate : pathPredicates.subList(1, pathPredicates.size())) {
            AsyncPredicate<ServerWebExchange> found = lookup(routeDefinition, andPredicate);
            pathPredicate = pathPredicate.or(found);
        }
    }
    //"AND" together the uber path predicate and the rest of the predicates for the route
    AsyncPredicate<ServerWebExchange> predicate;
    List<PredicateDefinition> predicateSubList;
    if(pathPredicate != null) {
        predicate = pathPredicate;
        predicateSubList = predicates;
    } else {
        predicate =  lookup(routeDefinition, predicates.get(0));
        predicateSubList = predicates.subList(1, predicates.size());
    }
    for (PredicateDefinition andPredicate : predicateSubList) {
        AsyncPredicate<ServerWebExchange> found = lookup(routeDefinition, andPredicate);
        predicate = predicate.and(found);
    }
    return predicate;
}

然后,用这个新类覆盖声明的routeDefinitionRouteLocator RouteLocator @Bean配置GatewayAutoConfiguration.java可以使用新的逻辑。

于 2018-08-27T22:48:55.507 回答