周丽艳 發表於 2025-7-9 14:31:00

掌握 Spring Cloud Gateway 的 13 种路由方式:轻松构建灵活微服务网关

<p>本文已收录在Github,<strong>关注我,紧跟本系列专栏文章,咱们下篇再续!</strong></p>
<ul>
<li>🚀 魔都架构师 | 全网30W技术追随者</li>
<li>🔧 大厂分布式系统/数据中台实战专家</li>
<li>🏆 主导交易系统百万级流量调优 &amp; 车联网平台架构</li>
<li>🧠 AIGC应用开发先行者 | 区块链落地实践者</li>
<li>🌍 以技术驱动创新,我们的征途是改变世界!</li>
<li>👉 实战干货:编程严选网</li>
</ul>
<p>Spring Cloud Gateway 支持多种路由模式,主要通过配置不同的 <code>RouteLocator</code> 或使用配置文件(如 <code>application.yml</code> 或 <code>application.properties</code>)来定义。</p>
<p>Spring Cloud Gateway 在 Spring WebFlux 的 <code>HandlerMapping</code> 基础设施中匹配路由。它内置了许多路由谓词工厂,这些谓词根据 HTTP 请求的不同属性进行匹配。你可以通过逻辑 <code>and</code> 组合多个谓词来实现更复杂的匹配逻辑。</p>
<h2 id="1-path-路由谓词工厂">1 Path 路由谓词工厂</h2>
<p><code>Path</code> 谓词工厂接收路径模式列表和一个可选参数 <code>matchTrailingSlash</code>(默认为 <code>true</code>)。示例:</p>
<pre><code class="language-yaml">spring:
cloud:
    gateway:
      routes:
      - id: path_route
      uri: https://example.org
      predicates:
      - Path=/red/{segment},/blue/{segment}
</code></pre>
<p>该路由匹配如 <code>/red/1</code>、<code>/red/1/</code>、<code>/red/blue</code> 或 <code>/blue/green</code> 的路径。</p>
<p>如果 <code>matchTrailingSlash</code> 设置为 <code>false</code>,则 <code>/red/1/</code> 不会匹配。</p>
<p>若设置了 <code>spring.webflux.base-path</code>,其值会自动添加到路径前。例如设置为 <code>/app</code>,匹配路径将为 <code>/app/red/{segment}</code>。</p>
<p>提取的 URI 模板变量(如 <code>segment</code>)可通过以下方式获取:</p>
<pre><code class="language-java">Map&lt;String, String&gt; uriVariables = ServerWebExchangeUtils.getUriTemplateVariables(exchange);
String segment = uriVariables.get("segment");
</code></pre>
<p>根据请求的路径进行路由。例如,将所有以 <code>/api/**</code> 开头的请求路由到某个服务。</p>
<pre><code class="language-yaml">spring:
cloud:
    gateway:
      routes:
      - id: path_route
      uri: http://example.com
      predicates:
      - Path=/api/**
</code></pre>
<h2 id="2-host-路由谓词工厂">2 Host 路由谓词工厂</h2>
<p><code>Host</code> 谓词工厂接收一个参数:主机名的模式列表(使用 Ant 风格语法,<code>.</code> 作为分隔符)。示例:</p>
<pre><code class="language-yaml">spring:
cloud:
    gateway:
      routes:
      - id: host_route
      uri: https://example.org
      predicates:
      - Host=**.somehost.org,**.anotherhost.org
</code></pre>
<p>该路由匹配如 <code>www.somehost.org</code>、<code>beta.somehost.org</code> 或 <code>www.anotherhost.org</code> 的请求。</p>
<p>如果使用 URI 模板变量(如 <code>{sub}.myhost.org</code>),匹配到的值会被放入 <code>ServerWebExchange.getAttributes()</code> 中,并可供 <code>GatewayFilter</code> 工厂 使用。</p>
<h2 id="3-query-路由谓词工厂">3 Query 路由谓词工厂</h2>
<p><code>Query</code> 谓词工厂接收一个必需参数 <code>param</code>,及可选正则表达式 <code>regexp</code>。</p>
<p>示例:</p>
<pre><code class="language-yaml">spring:
cloud:
    gateway:
      routes:
      - id: query_route
      uri: https://example.org
      predicates:
      - Query=red, gree.
</code></pre>
<p>该路由匹配 <code>red</code> 查询参数,且值匹配正则 <code>gree.</code>,如 <code>green</code> 和 <code>greet</code>。</p>
<h2 id="4-header-路由谓词工厂">4 Header 路由谓词工厂</h2>
<p><code>Header</code> 谓词工厂接收两个参数:<code>header</code> 名称和正则表达式。用于匹配指定请求头名称和值的请求。</p>
<p>示例:</p>
<pre><code class="language-yaml">spring:
cloud:
    gateway:
      routes:
      - id: header_route
      uri: https://example.org
      predicates:
      - Header=X-Request-Id, \d+
</code></pre>
<p>该路由匹配带有 <code>X-Request-Id</code> 请求头,且其值为数字(<code>\d+</code>)的请求。基于头的路由</p>
<p>根据请求的头信息进行路由。例如,将所有包含 <code>X-Request-Id=123</code> 的请求路由到某个服务。</p>
<pre><code class="language-yaml">spring:
cloud:
    gateway:
      routes:
      - id: header_route
      uri: http://example.com
      predicates:
      - Header=X-Request-Id,123
</code></pre>
<h2 id="5-基于cookie的路由">5 基于Cookie的路由</h2>
<p><code>Cookie</code> 谓词工厂接收两个参数:cookie 的 <code>name</code> 和一个正则表达式 <code>regexp</code>(Java 格式)。用于匹配指定名称且值符合正则的 Cookie。</p>
<p>根据请求的Cookie进行路由。例如,将所有包含 <code>session=123</code> 的Cookie的请求路由到某个服务。</p>
<pre><code class="language-yaml">spring:
cloud:
    gateway:
      routes:
      - id: cookie_route
      uri: http://example.com
      predicates:
      - Cookie=session,123
</code></pre>
<h2 id="6-method-路由谓词工厂">6 Method 路由谓词工厂</h2>
<p><code>Method</code> 谓词工厂接收一个或多个 HTTP 方法作为参数。示例:</p>
<pre><code class="language-yaml">spring:
cloud:
    gateway:
      routes:
      - id: method_route
      uri: https://example.org
      predicates:
      - Method=GET,POST
</code></pre>
<p>该路由匹配请求方法为 <code>GET</code> 或 <code>POST</code> 的请求。</p>
<h2 id="7-after-路由谓词工厂">7 After 路由谓词工厂</h2>
<p><code>After</code> 谓词工厂接收一个参数:<code>datetime</code>(类型为 Java 的 <code>ZonedDateTime</code>)。该谓词用于匹配发生在指定时间之后的请求。示例如下:</p>
<pre><code class="language-yaml">spring:
cloud:
    gateway:
      routes:
      - id: after_route
      uri: https://example.org
      predicates:
      - After=2017-01-20T17:42:47.789-07:00
</code></pre>
<p>该路由将匹配在 2017 年 1 月 20 日 17:42(美国丹佛时间)之后发出的所有请求。</p>
<h2 id="8-before-路由谓词工厂">8 Before 路由谓词工厂</h2>
<p><code>Before</code> 谓词工厂也接收一个 <code>datetime</code> 参数,用于匹配指定时间之前的请求。示例:</p>
<pre><code class="language-yaml">spring:
cloud:
    gateway:
      routes:
      - id: before_route
      uri: https://example.org
      predicates:
      - Before=2017-01-20T17:42:47.789-07:00
</code></pre>
<p>该路由匹配在 2017 年 1 月 20 日 17:42(丹佛时间)之前发出的请求。</p>
<h2 id="9-between-路由谓词工厂">9 Between 路由谓词工厂</h2>
<p><code>Between</code> 谓词工厂接收两个参数:<code>datetime1</code> 和 <code>datetime2</code>(都是 Java 的 <code>ZonedDateTime</code> 对象)。该谓词匹配发生在 <code>datetime1</code> 和 <code>datetime2</code> 之间的请求。<code>datetime2</code> 必须晚于 <code>datetime1</code>。示例:</p>
<pre><code class="language-yaml">spring:
cloud:
    gateway:
      routes:
      - id: between_route
      uri: https://example.org
      predicates:
      - Between=2017-01-20T17:42:47.789-07:00, 2017-01-21T17:42:47.789-07:00
</code></pre>
<p>该路由匹配在 2017 年 1 月 20 日 17:42 到 2017 年 1 月 21 日 17:42(丹佛时间)之间的请求,常用于维护时间段控制。</p>
<h2 id="10-remoteaddr-路由谓词工厂">10 RemoteAddr 路由谓词工厂</h2>
<p><code>RemoteAddr</code> 谓词工厂接收一个 CIDR 格式的地址列表(IPv4 或 IPv6)。示例:</p>
<pre><code class="language-yaml">spring:
cloud:
    gateway:
      routes:
      - id: remoteaddr_route
      uri: https://example.org
      predicates:
      - RemoteAddr=192.168.1.1/24
</code></pre>
<p>该路由匹配远程地址为 <code>192.168.1.10</code> 的请求。</p>
<h3 id="修改远程地址的解析方式">修改远程地址的解析方式</h3>
<p>默认情况下,该谓词使用请求中的远程地址。如果网关处于代理之后,这可能不是实际客户端 IP。</p>
<p>可以通过设置自定义 <code>RemoteAddressResolver</code> 来改变解析方式。Spring Cloud Gateway 提供了一个基于 X-Forwarded-For 头的实现:<code>XForwardedRemoteAddressResolver</code>。</p>
<p>该类提供两个静态方法:</p>
<ul>
<li><code>trustAll</code>:使用 <code>X-Forwarded-For</code> 中第一个 IP 地址,容易被伪造。</li>
<li><code>maxTrustedIndex</code>:根据可信代理层数确定可信 IP 的索引。</li>
</ul>
<p>示例头部:</p>
<pre><code class="language-none">X-Forwarded-For: 0.0.0.1, 0.0.0.2, 0.0.0.3
</code></pre>
<p>不同 <code>maxTrustedIndex</code> 值对应的解析结果如下:</p>
<table>
<thead>
<tr>
<th>maxTrustedIndex</th>
<th>结果</th>
</tr>
</thead>
<tbody>
<tr>
<td>[<code>Integer.MIN_VALUE</code>, 0]</td>
<td>初始化时抛出异常</td>
</tr>
<tr>
<td>1</td>
<td>0.0.0.3</td>
</tr>
<tr>
<td>2</td>
<td>0.0.0.2</td>
</tr>
<tr>
<td>3</td>
<td>0.0.0.1</td>
</tr>
<tr>
<td></td>
<td>0.0.0.1</td>
</tr>
</tbody>
</table>
<p>Java 配置示例:</p>
<pre><code class="language-java">RemoteAddressResolver resolver = XForwardedRemoteAddressResolver
    .maxTrustedIndex(1);

...

.route("direct-route",
    r -&gt; r.remoteAddr("10.1.1.1", "10.10.1.1/24")
      .uri("https://downstream1")
.route("proxied-route",
    r -&gt; r.remoteAddr(resolver, "10.10.1.1", "10.10.1.1/24")
      .uri("https://downstream2")
)
</code></pre>
<h2 id="11-weight-路由谓词工厂">11 Weight 路由谓词工厂</h2>
<p><code>Weight</code> 谓词工厂接收两个参数:<code>group</code> 和 <code>weight</code>(整数),权重在组内计算。示例:</p>
<pre><code class="language-yaml">spring:
cloud:
    gateway:
      routes:
      - id: weight_high
      uri: https://weighthigh.org
      predicates:
      - Weight=group1, 8
      - id: weight_low
      uri: https://weightlow.org
      predicates:
      - Weight=group1, 2
</code></pre>
<p>大约 80% 的请求会被转发到 <code>weighthigh.org</code>,20% 转发到 <code>weightlow.org</code>。</p>
<h2 id="12-xforwardedremoteaddr-路由谓词工厂">12 XForwardedRemoteAddr 路由谓词工厂</h2>
<p>该谓词工厂接收 CIDR 格式地址列表,用于根据 <code>X-Forwarded-For</code> 头过滤请求。常用于部署在反向代理之后的场景,只允许来自可信 IP 的请求通过。</p>
<p>示例:</p>
<pre><code class="language-yaml">spring:
cloud:
    gateway:
      routes:
      - id: xforwarded_remoteaddr_route
      uri: https://example.org
      predicates:
      - XForwardedRemoteAddr=192.168.1.1/24
</code></pre>
<p>当请求头中的 <code>X-Forwarded-For</code> 包含如 <code>192.168.1.10</code> 的地址时,该路由匹配成功。</p>
<h2 id="13-组合路由">13 组合路由</h2>
<p>可以组合多个谓词(Predicates)来实现更复杂的路由逻辑。例如,将所有来自 <code>example.com</code> 且路径以 <code>/api/**</code> 开头的请求路由到某个服务。</p>
<pre><code class="language-yaml">spring:
cloud:
    gateway:
      routes:
      - id: combined_route
      uri: http://example.com
      predicates:
      - Host=example.com
      - Path=/api/**
</code></pre>
<p>这些路由模式可以根据实际需求进行灵活组合,以满足不同的业务场景。Spring Cloud Gateway 提供了强大的路由功能,使得微服务架构中的请求路由更加灵活和可配置。</p>
<pre><code class="language-yaml">      - Path=/api/**
</code></pre>
<p>这些路由模式可以根据实际需求灵活组合,以适应各种业务场景。Spring Cloud Gateway 提供了强大的路由功能,使微服务架构中的请求路由变得更加灵活和可配置。</p>
<blockquote>
<p>本文由博客一文多发平台 OpenWrite 发布!</p>
</blockquote><br><br>
来源:https://www.cnblogs.com/JavaEdge/p/18974778
頁: [1]
查看完整版本: 掌握 Spring Cloud Gateway 的 13 种路由方式:轻松构建灵活微服务网关