spring cloud gateway

spring cloud gateway

1. 基本路由配置


spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: lb://USER-SERVICE  # 使用负载均衡
          predicates:
            - Path=/user/**
          filters:
            - StripPrefix=1

说明

  • id:路由的唯一 ID
  • uri:目标服务地址,支持 http://lb://(负载均衡)
  • predicates:断言规则,决定请求是否匹配该路由
  • filters:过滤规则,对请求或响应进行修改

2. 断言(Predicates)

Spring Cloud Gateway 提供了多种请求匹配规则(断言),可以用来判断某个请求是否符合当前路由。

常见断言

predicates:
  - Path=/api/**                     # 匹配路径
  - Method=GET,POST                  # 限制 HTTP 方法
  - Host=**.example.***               # 匹配域名
  - Header=X-Request-Id, \d+          # 请求头匹配
  - Query=token                       # 请求参数必须包含 token
  - Before=2025-12-31T23:59:59.999Z   # 在某个时间之前生效
  - After=2025-01-01T00:00:00.000Z    # 在某个时间之后生效
  - Between=2025-01-01T00:00:00.000Z, 2025-12-31T23:59:59.999Z # 时间范围
  - RemoteAddr=192.168.1.1/24         # 限制 IP 地址
  - Weight=group1, 5                 # 按指定权重负载均衡,group1 组内权重为 5
  - Cookie=SESSIONID, abc123          # 包含名为 SESSIONID 的 Cookie,且值必须匹配 abc123
  - XForwardedRemoteAddr=192.168.1.0/24  # 从 X-Forwarded-For 请求头解析 IP,限制来源于 
                                           192.168.1.0/24 网段

这里要求访问路径要求满足Path和Query才会访问uri


 3. 过滤器(Filters)

过滤器用于修改请求或响应,可以在网关层面进行鉴权、限流、日志记录等操作。

常见过滤器

filters:
  - StripPrefix=1                  # 去掉第一级路径
  - AddRequestHeader=Token, abc123  # 给请求添加请求头
  - AddResponseHeader=X-Response, OK  # 给响应添加请求头
  - RewritePath=/api/(?<segment>.*), /newpath/$\{segment}  # 路径重写
  - SetStatus=404                   # 修改返回状态码
  - Retry=5                          # 失败重试 5 次
  - RequestRateLimiter=redis-rate-limiter  # 基于 Redis 令牌桶算法限流

4. 全局超时设置

可以配置连接超时、读取超时,防止服务长时间无响应:

spring:
  cloud:
    gateway:
      httpclient:
        connect-timeout: 5000  # 连接超时 5 秒
        response-timeout: 10s  # 读取超时 10 秒

5. CORS 跨域配置

如果前端需要跨域访问 API,需要在网关中开启 CORS:

spring:
  cloud:
    gateway:
      globalcors:
        corsConfigurations:
          '[/**]': # 匹配所有路径
            allowedOrigins: "https://example.***"  # 允许的来源
            allowedMethods:  # 允许的请求方法
              - GET
              - POST
              - PUT
              - DELETE
            allowedHeaders: "*"  # 允许所有请求头
            allowCredentials: true  # 允许携带 Cookie

 6. 限流(Request Rate Limiting)

Spring Cloud Gateway 支持基于 Redis 的令牌桶限流,限制单位时间内的请求数:

spring:
  cloud:
    gateway:
      routes:
        - id: limit_route
          uri: http://localhost:8080
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 10  # 每秒补充 10 个令牌
                redis-rate-limiter.burstCapacity: 20  # 令牌桶最大容量
                key-resolver: "#{@ipKeyResolver}"  # 根据 IP 进行限流

💡 需要在 @Bean 中定义 ipKeyResolver

@Bean
public KeyResolver ipKeyResolver() {
    return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostString());
}

7. 负载均衡(Load Balancer)

Spring Cloud Gateway 可与 Spring Cloud LoadBalancer 结合,动态选择可用的微服务:

spring:
  cloud:
    gateway:
      routes:
        - id: service-route
          uri: lb://USER-SERVICE  # 通过服务名进行负载均衡
          predicates:
            - Path=/user/**

⚠️ 需要引入 spring-cloud-starter-loadbalancer 依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

 8. 断路器(Circuit Breaker)

Spring Cloud Gateway 可以与 Resilience4j 结合,避免微服务雪崩:

filters:
  - name: CircuitBreaker
    args:
      name: myCircuitBreaker
      fallbackUri: forward:/fallback

💡 需要配置 Resilience4j

resilience4j:
  circuitbreaker:
    instances:
      myCircuitBreaker:
        sliding-window-size: 10
        failure-rate-threshold: 50
        wait-duration-in-open-state: 5000ms

9. 日志 & 监控

可以启用 Spring Boot Actuator 进行监控:

management:
  endpoints:
    web:
      exposure:
        include: gateway

10.自定义断言工厂

创建一个“时间范围”断言工厂,控制请求只能在指定时间范围内访问

(1)创建自定义 Predicate 工厂类

在 Spring Cloud Gateway 中,自定义断言工厂必须继承 AbstractRoutePredicateFactory<T>,并且 类名必须以 RoutePredicateFactory 结尾

import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.stereotype.***ponent;
import java.time.LocalTime;
import java.util.function.Predicate;
import org.springframework.web.server.ServerWebExchange;

@***ponent
public class TimeBetweenRoutePredicateFactory extends AbstractRoutePredicateFactory<TimeBetweenRoutePredicateFactory.Config> {

    public TimeBetweenRoutePredicateFactory() {
        super(Config.class);
    }

    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        return exchange -> {
            // 获取当前时间
            LocalTime now = LocalTime.now();
            // 检查当前时间是否在配置的时间范围内
            return now.isAfter(config.getStartTime()) && now.isBefore(config.getEndTime());
        };
    }

    // 这个方法用于绑定 yml 配置中的参数
    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("startTime", "endTime");
    }

    // 配置类
    public static class Config {
        private LocalTime startTime;
        private LocalTime endTime;

        public LocalTime getStartTime() {
            return startTime;
        }

        public void setStartTime(LocalTime startTime) {
            this.startTime = startTime;
        }

        public LocalTime getEndTime() {
            return endTime;
        }

        public void setEndTime(LocalTime endTime) {
            this.endTime = endTime;
        }
    }
}

📌 解释

  • 继承 AbstractRoutePredicateFactory<Config>
    • 这里的 Config 是一个内部类,用于接收 YAML 配置中的参数startTimeendTime)。
  • apply(Config config)
    • 逻辑:获取当前时间,判断是否在 startTimeendTime 之间。
  • shortcutFieldOrder()
    • 指定 YAML 配置中参数的顺序(必须与 Config 类的字段一致)。
  • exchange 是 Spring Cloud Gateway 处理请求时,由 WebFlux 框架自动创建并传递的,你只需要在 过滤器、断言工厂等组件 中直接使用它即可

(2)在 application.yml 中使用

spring:
  cloud:
    gateway:
      routes:
        - id: time_based_route
          uri: http://localhost:8080
          predicates:
            - name: TimeBetween
              args:
                startTime: "08:00"
                endTime: "18:00"

📌 解释

  • 这个路由规则表示:只能在 08:00 - 18:00 之间访问,否则请求不会被转发

假设你要拦截某些特定的 User-Agent(比如禁止 curl 访问)

(1)基于 User-Agent 判断

@***ponent
public class UserAgentRoutePredicateFactory extends AbstractRoutePredicateFactory<UserAgentRoutePredicateFactory.Config> {

    public UserAgentRoutePredicateFactory() {
        super(Config.class);
    }

    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        return exchange -> {
            String userAgent = exchange.getRequest().getHeaders().getFirst("User-Agent");
            return userAgent != null && !userAgent.toLowerCase().contains(config.getBlockedUserAgent().toLowerCase());
        };
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("blockedUserAgent");
    }

    public static class Config {
        private String blockedUserAgent;

        public String getBlockedUserAgent() {
            return blockedUserAgent;
        }

        public void setBlockedUserAgent(String blockedUserAgent) {
            this.blockedUserAgent = blockedUserAgent;
        }
    }
}

(2)YAML 配置

spring:
  cloud:
    gateway:
      routes:
        - id: block_curl
          uri: http://localhost:8080
          predicates:
            - name: UserAgent
              args:
                blockedUserAgent: "curl"

📌 效果

  • 如果 User-Agent 包含 "curl",请求将被拦截。

11.过滤器详述

在 Spring Cloud Gateway 中,过滤器(Filter) 是网关处理请求的重要组成部分。它可以对请求响应进行拦截、修改或增强,比如:

  • 权限认证(JWT 解析、OAuth2 认证)
  • 日志记录(记录请求时间、请求路径)
  • 限流处理(Redis 令牌桶限流)
  • 修改请求(添加/删除 Header、修改 Body)
  • 修改响应(统一返回格式、添加 CORS 头)

📌 1. 过滤器的分类

Spring Cloud Gateway 过滤器分为 两大类

类型 作用 执行顺序
GatewayFilter(局部过滤器) 针对单个路由生效,只能在 application.ymlroutes 里配置 在请求匹配到某个路由后执行
GlobalFilter(全局过滤器) 对所有路由生效,用于全局日志、权限认证等 所有请求都会执行

📌 2. 局部过滤器(GatewayFilter)

(1)常见内置过滤器

Spring Cloud Gateway 提供了很多 内置的 GatewayFilter,可以直接在 application.yml 里配置:

spring:
  cloud:
    gateway:
      routes:
        - id: my_route
          uri: http://localhost:8080
          predicates:
            - Path=/api/**
          filters:
            - AddRequestHeader=Authorization, Bearer 123456  # 添加请求头
            - AddResponseHeader=X-Response-Time, 100ms       # 添加响应头
            - RewritePath=/old/(?<segment>.*), /new/$\{segment}  # 修改请求路径
            - RemoveRequestParameter=token   # 移除请求参数

📌 内置过滤器说明

过滤器 作用
AddRequestHeader 添加请求头(示例:Authorization: Bearer 123456
AddResponseHeader 添加响应头(示例:X-Response-Time: 100ms
RewritePath 修改请求路径(示例:/old/user/new/user
RemoveRequestParameter 删除指定的请求参数

(2)自定义局部过滤器

如果内置 GatewayFilter 不能满足需求,可以自定义过滤器,比如统计请求时间

import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.***ponent;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@***ponent
public class RequestTimeGatewayFilterFactory extends AbstractGatewayFilterFactory<RequestTimeGatewayFilterFactory.Config> {

    public RequestTimeGatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            long startTime = System.currentTimeMillis();
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                long endTime = System.currentTimeMillis();
                System.out.println("请求耗时:" + (endTime - startTime) + "ms");
            }));
        };
    }

    public static class Config {
        // 这里可以添加需要的配置参数
    }
}

📌 如何在 application.yml 里使用?

spring:
  cloud:
    gateway:
      routes:
        - id: time_filter_route
          uri: http://localhost:8080
          predicates:
            - Path=/api/**
          filters:
            - name: RequestTime

📌 效果

  • 这个过滤器会计算每个请求的耗时并打印日志。

📌 3. 全局过滤器(GlobalFilter)

如果你想对所有请求进行拦截(比如日志记录、鉴权),需要使用 GlobalFilter

(1)定义全局过滤器

import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.Ordered;
import org.springframework.stereotype.***ponent;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@***ponent
public class CustomGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("🔹 全局过滤器:请求路径 " + exchange.getRequest().getURI().getPath());

        // 继续执行下一个过滤器
        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            System.out.println("🔹 响应返回,状态码:" + exchange.getResponse().getStatusCode());
        }));
    }

    @Override
    public int getOrder() {
        return -1; // 数字越小,优先级越高(-1 代表最早执行)
    }
}

📌 解释

  • GlobalFilter:全局生效,无需在 application.yml 里配置,所有请求都会执行。
  • Ordered:用于控制执行顺序,数字越小优先级越高(-1 代表最早执行)。

(2)高级示例:JWT 认证

如果你需要拦截请求并校验 JWT 令牌

@***ponent
public class JwtAuthGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");

        if (token == null || !token.startsWith("Bearer ")) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().set***plete();
        }

        return chain.filter(exchange); // 继续请求
    }

    @Override
    public int getOrder() {
        return -10; // 优先级比默认 GlobalFilter 高
    }
}

📌 效果

  • 如果请求头里没有 Authorization 或者格式不正确,返回 401 Unauthorized

📌 4. 过滤器执行顺序

🌟 过滤器执行流程

1️⃣ GlobalFilter(前置逻辑)
2️⃣ GatewayFilter(局部过滤器)
3️⃣ 真正访问目标服务http://localhost:8080
4️⃣ GatewayFilter(后置逻辑)
5️⃣ GlobalFilter(后置逻辑)


✅ 总结

过滤器类型 生效范围 适用场景 定义方式
GatewayFilter(局部) 只针对某个路由 日志记录、参数修改、Header 操作 application.ymlAbstractGatewayFilterFactory
GlobalFilter(全局) 所有请求都会经过 JWT 鉴权、日志、全局限流 GlobalFilter 接口

📌5.Spring Cloud Gateway 实现全局跨域(CORS 配置)

1. 在 application.yml 中配置 CORS(推荐 ✅)

Spring Cloud Gateway 支持直接在 application.yml 配置跨域,简单方便:

spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':   # 允许所有路径
            allowedOrigins: "*"   # 允许所有来源(可指定前端域名,如 "http://example.***")
            allowedMethods: "*"   # 允许所有请求方法(GET, POST, PUT, DELETE等)
            allowedHeaders: "*"   # 允许所有请求头
            allowCredentials: true  # 允许携带 Cookie

优点

  • 配置简单,适用于大多数场景。
  • 支持 Spring Boot 2.4+ 及 Spring Cloud Gateway 原生跨域处理

 2. 使用 CorsWebFilter 配置全局 CORS

如果 application.yml 配置不生效,可以使用 CorsWebFilter 代码配置:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsWebFilter;

import java.util.Arrays;

@Configuration
public class GlobalCorsConfig {

    @Bean
    public CorsWebFilter corsWebFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowedOrigins(Arrays.asList("*"));  // 允许所有来源
        config.setAllowedMethods(Arrays.asList("*"));  // 允许所有请求方法
        config.setAllowedHeaders(Arrays.asList("*"));  // 允许所有请求头
        config.setAllowCredentials(true); // 允许携带 Cookie

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);

        return new CorsWebFilter(source);
    }
}

优点

  • 代码方式更灵活,可以动态配置。
  • 可以针对不同路径设置不同 CORS 规则

 3. 在 GlobalFilter 里手动设置 CORS 响应头

如果 CorsWebFilter 也无法满足需求,你可以在自定义全局过滤器里手动设置 CORS 头:

import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.***ponent;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@***ponent
public class CorsGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpResponse response = exchange.getResponse();
        HttpHeaders headers = response.getHeaders();

        headers.add("A***ess-Control-Allow-Origin", "*"); // 允许所有域
        headers.add("A***ess-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        headers.add("A***ess-Control-Allow-Headers", "*");
        headers.add("A***ess-Control-Allow-Credentials", "true");

        // 处理 OPTIONS 预检请求
        if (exchange.getRequest().getMethod() == HttpMethod.OPTIONS) {
            response.setStatusCode(org.springframework.http.HttpStatus.OK);
            return response.set***plete();
        }

        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }
}

适用于特殊场景

  • 想在某个全局过滤器里控制跨域
  • OPTIONS 预检请求做特殊处理
  • 动态调整跨域规则
转载请说明出处内容投诉
CSS教程网 » spring cloud gateway

发表评论

欢迎 访客 发表评论

一个令你着迷的主题!

查看演示 官网购买