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 访问订单服务。如下图:

上图请求成功,是因为携带了一个 title 参数,值为 hello。如果此时我们修改路由为如下:
# Query断言:如果请求包含 title 参数,值为 人人编程网,则匹配该路由 - Query=title,人人编程网
重启网关服务,再次使用上面请求参数发送请求,如下图:

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

请求成功了。
下面是 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;
// 配置信息
}
}