Gateway Host 路由断言工厂

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 头信息,如下图:

Gateway Host 路由断言工厂

上图可知,成功访问到订单接口。如果我们将 host 请求头的值修改为 www.baidu.com,请求将会失败,如下图:

Gateway Host 路由断言工厂

源码分析

下面是 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<>();

       // 配置信息
    }
}


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