Gateway Query 路由断言工厂

Query 路由断言工厂需要两个参数:一个必填参数和一个可选 regexp(Java 正则表达式)。语法格式:

Query=参数名, 参数值(支持正则表达式)

例如:

spring:
 cloud:
   gateway:
     routes:
     - id: query_route
       uri: https://example.org
       predicates:
       - Query=green

上述配置,如果请求包含 green 查询参数,则上面的路由匹配。修改配置:

spring:
 cloud:
   gateway:
     routes:
     - id: query_route
       uri: https://example.org
       predicates:
       - Query=red, gree.

上述配置,如果请求中包含 red 查询参数,并且该参数的值与“gree.”正则表达式(.表示任何字符,如 green 和 greet)匹配,则匹配名为 query_route 的路由。

示例

将“Gateway 搭建网关服务”项目的配置文件 bootstrap.yml 内容使用如下配置替换:

server:
  # 网关端口
  port: 9000

spring:
  application:
    # 服务名称
    name: gateway-demo01
  cloud:
    # nacos
    nacos:
      discovery:
        server-addr: localhost:8848
        username: nacos
        password: nacos
        group: DEFAULT_GROUP

    # 网关路由配置
    gateway:
      # 网关路由配置
      routes:
        # 路由id,自定义,只要唯一集合
        - id: service-order
          # 路由的目标地址,lb 就是负载均衡,后面跟服务名
          # 需要集成 nacos 等服务注册中心
          uri: lb://service-order
          # 路由断言,也就是判断请求是否符合路由规则的条件
          predicates:
            # Query断言:如果请求包含 title 参数,则匹配该路由
            - Query=title

修改好配置后,重启网关服务,使用 Postman 访问订单服务。如下图:

Gateway Query 路由断言工厂

上图请求成功,是因为携带了一个 title 参数,值为 hello。如果此时我们修改路由为如下:

# Query断言:如果请求包含 title 参数,值为 人人编程网,则匹配该路由
- Query=title,人人编程网

重启网关服务,再次使用上面请求参数发送请求,如下图:

Gateway Query 路由断言工厂

从上图可知,请求失败了,这是因为 title 参数的值和我们配置的值不匹配,如果将 title 参数的值改为“人人编程网”,再次发送请求,如下图:

Gateway Query 路由断言工厂

请求成功了。

源码分析

下面是 Query 路由断言工厂源码:

package org.springframework.cloud.gateway.handler.predicate;

//...

public class QueryRoutePredicateFactory extends AbstractRoutePredicateFactory<QueryRoutePredicateFactory.Config> {

    public static final String PARAM_KEY = "param";
    public static final String REGEXP_KEY = "regexp";

    public QueryRoutePredicateFactory() {
       super(Config.class);
    }

    @Override
    public List<String> shortcutFieldOrder() {
       return Arrays.asList(PARAM_KEY, REGEXP_KEY);
    }

    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
       return exchange -> {
          // 如果没有指定匹配的正则表达式,则判断请求是否包含指定的头
          if (!StringUtils.hasText(config.regexp)) {
             // check existence of header
             return exchange.getRequest().getQueryParams().containsKey(config.param);
          }

          // 从请求中获取指定参数的值
          List<String> values = exchange.getRequest().getQueryParams().get(config.param);
          if (values == null) {
             return false;
          }
          
          // 迭代匹配参数值
          for (String value : values) {
             if (value != null && value.matches(config.regexp)) {
                return true;
             }
          }
          return false;
       };
    }

    @Validated
    public static class Config {
       // 参数名
       @NotEmpty
       private String param;
       // 匹配的正则表达式
       private String regexp;
       // 配置信息
    }
}
说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号