Host 路由断言工厂只需一个参数:host 值模式列表。模式是以 “.” 为分隔符的 Ant 风格模式。语法如下:
Host=host1,host2,....,hostN
该断言会匹配与该模式匹配的 HTTP 请求的 Host 头,多个 host 名使用逗号(,)分割。例如:
spring: cloud: gateway: routes: - id: host_route uri: https://example.org predicates: - Host=**.somehost.org,**.anotherhost.org
注意,Host 断言的值也支持 URI 模板变量,如:{Sub}.myhost.org。如果请求的 Host 标头值为 www.somehost.org 或 beta.somehost.org 或 www.anotherhost.org,则此路由匹配。
该断言将 URI 模板变量(如上例中定义的 sub)提取为名称和值的映射,并将其放入 ServerWebExchange.getAttributes() 中,其关键字定义在ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE 中,这些值随后可供 GatewayFilter 工厂使用
将“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: # Host断言:匹配 host 头为 hxstrive.com 域名的请求,如:www.hxstrive.com、doc.hxstrive.com - Host=**.hxstrive.com
修改好配置后,重启网关服务,使用 Postman 访问订单服务。注意,在访问服务时添加 host 头信息,如下图:
上图可知,成功访问到订单接口。如果我们将 host 请求头的值修改为 www.baidu.com,请求将会失败,如下图:
下面是 Host 路由断言工厂源码:
package org.springframework.cloud.gateway.handler.predicate; // ... public class HostRoutePredicateFactory extends AbstractRoutePredicateFactory<HostRoutePredicateFactory.Config> { // Ant 风格路径匹配器 private PathMatcher pathMatcher = new AntPathMatcher("."); public HostRoutePredicateFactory() { super(Config.class); } public void setPathMatcher(PathMatcher pathMatcher) { this.pathMatcher = pathMatcher; } @Override public List<String> shortcutFieldOrder() { return Collections.singletonList("patterns"); } @Override public ShortcutType shortcutType() { return ShortcutType.GATHER_LIST; } @Override public Predicate<ServerWebExchange> apply(Config config) { return exchange -> { // 获取第一个出现的 Host 字段 String host = exchange.getRequest().getHeaders().getFirst("Host"); // 逐一使用指定的模式匹配 Host 的值 Optional<String> optionalPattern = config.getPatterns().stream() .filter(pattern -> this.pathMatcher.match(pattern, host)) .findFirst(); // 如果匹配成功 if (optionalPattern.isPresent()) { // 提取 URI 中的变量值 Map<String, String> variables = this.pathMatcher.extractUriTemplateVariables(optionalPattern.get(), host); ServerWebExchangeUtils.putUriTemplateVariables(exchange, variables); return true; } return false; }; } @Validated public static class Config { private List<String> patterns = new ArrayList<>(); // 配置信息 } }