Header 信息路由断言工厂需要两个参数,即 header 信息和 regexp(Java 正则表达式)。语法如下:
Header=请求头名称, 请求头的值
该断言与具有给定名称且其值符合正则表达式的header 匹配。例如:
spring: cloud: gateway: routes: - id: header_route uri: https://example.org predicates: - Header=X-Request-Id, \d+
上面配置,如果 HTTP 请求的 header 名为 X-Request-Id,并且其值符合 \d+ 正则表达式(即其值为一位或多位数字),则该路由与之匹配。
将“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: # Header断言:匹配拥有名为 my_header,值为数字的请求头的请求 - Header=my_header, \d+
修改好配置后,重启网关服务,使用 Postman 访问订单服务。注意,在访问服务时添加 my_header 头信息,如下图:
上图可知,成功访问到订单接口。如果我们将请求头的值追加一个字符串(因此不满足 \d+ 正则表达式),请求将会失败,如下图:
下面是 Header 路由断言工厂源码:
package org.springframework.cloud.gateway.handler.predicate; //... public class HeaderRoutePredicateFactory extends AbstractRoutePredicateFactory<HeaderRoutePredicateFactory.Config> { public static final String HEADER_KEY = "header"; public static final String REGEXP_KEY = "regexp"; public HeaderRoutePredicateFactory() { super(Config.class); } @Override public List<String> shortcutFieldOrder() { return Arrays.asList(HEADER_KEY, REGEXP_KEY); } @Override public Predicate<ServerWebExchange> apply(Config config) { boolean hasRegex = !StringUtils.isEmpty(config.regexp); return exchange -> { // 获取指定请求头所有的值 List<String> values = exchange.getRequest().getHeaders().getOrDefault(config.header, Collections.emptyList()); if (values.isEmpty()) { // 如果为空,则返回 false return false; } // 如果指定的正则表达式不为空 // values is now guaranteed to not be empty if (hasRegex) { // 使用 JDK8 流操作,匹配请求头的值列表,匹配任何一个,则返回 true // check if a header value matches return values.stream().anyMatch(value -> value.matches(config.regexp)); } // there is a value and since regexp is empty, we only check existence. return true; }; } @Validated public static class Config { // HTTP 请求头名称 @NotEmpty private String header; // 请求头字段值匹配的正则表达式 private String regexp; // 配置信息 } }