本文介绍了如何“删除gobal前缀('/api'),然后转到lb://"从Zuul迁移到Spring Cloud Gateway时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从zuul迁移到Spring Cloud Gateway,我不想更改以前应用程序的配置.我想知道如何处理带有"/api/+'serviceId'"的网址,并路由到lb://serviceId

I want to Migrating from zuul to spring cloud gateway, I don't want to change my config of previous app. I want to know how to handle with the url with "/api/ + 'serviceId'", route to lb://serviceId

以前的zuul配置

zuul: 
  prefix: /api

尤里卡(Eureka)有很多服务注册者,我不想为每个尤里卡(Eureka)配置路由.

there are lots of service regist to eureka ,i don't want to config a route for each one.

例如由org.springframework.cloud.gateway.discovery.DiscoveryClientRouteDefinitionLocator自动生成的路线

eg. the auto generated route by org.springframework.cloud.gateway.discovery.DiscoveryClientRouteDefinitionLocator

{
"route_id": "CompositeDiscoveryClient_APIGATEWAY",
"route_definition": {
  "id": "CompositeDiscoveryClient_APIGATEWAY",
  "predicates": [
    {
      "name": "Path",
      "args": {
        "pattern": "/apigateway/**"
      }
    }
  ],
  "filters": [
    {
      "name": "RewritePath",
      "args": {
        "regexp": "/apigateway/(?<remaining>.*)",
        "replacement": "/${remaining}"
      }
    }
  ],
  "uri": "lb://APIGATEWAY",
  "order": 0
}

我想要的是

 {
"route_id": "CompositeDiscoveryClient_APIGATEWAY",
"route_definition": {
  "id": "CompositeDiscoveryClient_APIGATEWAY",
  "predicates": [
    {
      "name": "Path",
      "args": {
        "pattern": "/api/apigateway/**"
      }
    }
  ],
  "filters": [
    {
      "name": "RewritePath",
      "args": {
        "regexp": "/api/apigateway/(?<remaining>.*)",
        "replacement": "/${remaining}"
      }
    }
  ],
  "uri": "lb://APIGATEWAY",
  "order": 0
}

我如何配置路线以获得我想要的东西

how can i config my route to get what i want

我还找到了源代码

    public static List<PredicateDefinition> initPredicates() {
    ArrayList<PredicateDefinition> definitions = new ArrayList<>();
    // TODO: add a predicate that matches the url at /serviceId?

    // add a predicate that matches the url at /serviceId/**
    PredicateDefinition predicate = new PredicateDefinition();
    predicate.setName(normalizeRoutePredicateName(PathRoutePredicateFactory.class));
    predicate.addArg(PATTERN_KEY, "'/'+serviceId+'/**'");
    definitions.add(predicate);
    return definitions;
}

'/'+ serviceId +'/**'"不带前缀

the "'/'+serviceId+'/**'" is there without a prefix

[2019-01-10]更新我认为@spencergibb的建议是一个很好的解决方案,但是(SpEL)遇到了新的麻烦我尝试了很多方法:

[2019-01-10] UPDATEI think @spencergibb's suggestion is a good solution, but I had new trouble with the (SpEL)I tried many ways:

args:
  regexp: "'/api/' + serviceId.toLowerCase() + '/(?<remaining>.*)'"
  replacement: '/${remaining}'
args:
  regexp: "'/api/' + serviceId.toLowerCase() + '/(?<remaining>.*)'"
  replacement: "'/${remaining}'"

启动失败

Origin: class path resource [application.properties]:23:70
Reason: Could not resolve placeholder 'remaining' in value "'${remaining}'"

当我使用转义符"\"时

when i use an escape "\" like

args:
  regexp: "'/api/' + serviceId.toLowerCase() + '/(?<remaining>.*)'"
  replacement: '/$\{remaining}'

启动成功,但运行时出现异常

it start success but i got an exception when running

org.springframework.expression.spel.SpelParseException: Expression [/$\{remaining}] @2: EL1065E: unexpected escape character.
at org.springframework.expression.spel.standard.Tokenizer.raiseParseException(Tokenizer.java:590) ~[spring-expression-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.expression.spel.standard.Tokenizer.process(Tokenizer.java:265) ~[spring-expression-5.0.5.RELEASE.jar:5.0.5.RELEASE]





更新2

我在org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterFactory中找到了一个替换项来处理"\"

I found in the org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterFactory, there's a replacement to deal with "\"

...    
@Override
        public GatewayFilter apply(Config config) {
            String replacement = config.replacement.replace("$\\", "$");
            return (exchange, chain) -> {
...

关于SpelParseException没有任何内容

推荐答案

您可以自定义通过属性使用的自动过滤器和谓词.

You can customize the automatic filters and predicates used via properties.

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
          predicates:
            - name: Path
              args:
                pattern: "'/api/'+serviceId.toLowerCase()+'/**'"
          filters:
            - name: RewritePath
              args:
                regexp: "'/api/' + serviceId.toLowerCase() + '/(?<remaining>.*)'"
                replacement: "'/${remaining}'"

请注意,值(即args.patternargs.regexp)都是Spring表达式语言(SpEL)表达式,因此单引号和+等...

Note the values (ie args.pattern or args.regexp) are all Spring Expression Language (SpEL) expressions, hence the single quotes and + etc...

如果不同的路由需要具有不同的前缀,则需要在属性中定义每个路由.

If different routes need to have different prefixes, you'd need to define each route in properties.

这篇关于如何“删除gobal前缀('/api'),然后转到lb://"从Zuul迁移到Spring Cloud Gateway时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-22 07:54