Spring Cloud Gateway:基础示例

发布: (2025年12月31日 GMT+8 02:03)
7 min read
原文: Dev.to

Source: Dev.to

Spring Cloud Gateway:基础示例的封面图片

Eduardo

Spring Cloud Gateway(也称为网关或 Edge Service)是一个动态路由服务器。换句话说,它让我们能够为微服务提供一个集中式的访问入口。此外,我们还可以通过添加过滤器或谓词等方式来扩展其功能。

1. Spring Cloud Gateway 配置

使用 Spring Initializr(或您喜欢的 IDE)创建一个项目,并确保选择以下依赖:

  • Eureka Discovery Client
  • Gateway

该项目也会被 Eureka Server 注册,因此添加以下配置:

@EnableEurekaClient
@SpringBootApplication
public class EurekaClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaClientApplication.class, args);
    }
}

应用属性(YAML)

spring:
  application:
    name: gateway-server-service
server:
  port: 8090
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka

Source:

2. 路由

Edge/Gateway 的最小必要配置是 路由。这些路由将请求从网关重定向到将响应请求的服务。

基本路由配置(YAML)

spring:
  cloud:
    gateway:
      routes:
        - id: employees
          uri: lb://employees
          predicates:
            - Path=/api/employees/**
          filters:
            - StripPrefix=2

说明

元素描述
id路由的唯一标识符。
uri网关查找要重定向的服务的地址。使用 Eureka 等服务发现时必须以 lb(负载均衡)开头。
predicates必须满足的重定向规则。
filters对通过声明路由的请求/响应进行操作的过滤器。

在上面的示例中,网关将请求路由到名为 employees 的微服务。要获取该服务的响应,只需调用网关的 Spring Cloud Gateway(端口 8090),而不是直接调用微服务的端口。

2.1 断言(Predicates)

断言是一组规则,只有满足这些规则才会成功重定向。它们可以基于路径、请求头、HTTP 方法、查询参数或 Cookie。

示例

predicates:
  - Path=/api/products/**
  - Header=token, \d+
  - Method=GET, POST
  - Query=color
  - Cookie=color, blue

含义

断言描述
Path重定向匹配声明路径的请求。
Header检查指定的请求头是否存在且其值匹配给定的正则表达式。
Method只允许列出的 HTTP 方法。
Query要求 URL 中必须包含给定的查询参数。
Cookie检查指定的 Cookie 是否存在(可选地匹配其值)。

2.2 Spring Cloud Gateway 工厂过滤器

工厂过滤器让你能够操作请求和响应(例如,添加请求头或请求参数)。

配置(YAML)

filters:
  - AddRequestHeader=token-request, 123456
  - AddResponseHeader=token-response, 12345678
  - SetResponseHeader=Content-Type, text/plain
  - AddRequestParameter=name, andres

这些过滤器仅在声明它们的路由上生效。

2.3 Spring Cloud Gateway 全局过滤器

全局过滤器会对 所有 通过网关的请求生效,无需在每条路由中单独声明。

示例实现

package com.funcionaenmimaquina.springboot.app.gateway.filters;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
public class ExampleGlobalFilter implements GlobalFilter, Ordered {

    private final Logger logger = LoggerFactory.getLogger(ExampleGlobalFilter.class);

    @Override
    public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        logger.info("Executing request filter");

        // Modifying the request
        exchange.getRequest()
                .mutate()
                .header("environment", "dev")
                .build();

        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            logger.info("Executing response filter");
            // Adding a cookie to the response
            exchange.getResponse()
                    .addCookie(ResponseCookie.from("myCookie", "myValue")
                            .path("/")
                            .maxAge(3600)
                            .build());
        }));
    }

    @Override
    public int getOrder() {
        // Lower values have higher precedence
        return -1;
}
}

在此示例中,过滤器会向每个传入请求添加一个 environment 头部,并向每个响应添加一个名为 myCookie 的 cookie。

全局过滤器示例(续)

o("Executing response filter");

// Modifying the response
Optional.ofNullable(exchange.getRequest().getHeaders().getFirst("environment"))
        .ifPresent(value -> {
            exchange.getResponse().getHeaders().add("env", value);
        });

exchange.getResponse().getHeaders().setContentType(MediaType.TEXT_PLAIN);
}))
;

@Override
public int getOrder() {
    return 1;
}
}

示例工作原理

  • 实现了 GlobalFilterOrdered 接口。
  • getOrder 定义了在存在多个全局过滤器时的执行顺序。
  • filter 方法包含所有与请求和响应交互的逻辑。
  • 第 24 行展示了可以在此处修改请求(例如,添加头部)。
  • 第 27 行展示了如何使用 .then(Mono.fromRunnable(...)) 来修改响应。
  • 第 31 行在响应中添加头部(前提是请求中存在特定头部)。
  • 第 34 行强制响应使用纯文本(text/plain)媒体类型。

2.4 过滤器工厂(自定义网关过滤器)

如果希望过滤器仅应用于选定的路由,可创建自定义过滤器工厂:

@Component
public class ExampleGatewayFilterFactory
        extends AbstractGatewayFilterFactory {

    private final Logger logger = LoggerFactory.getLogger(ExampleGatewayFilterFactory.class);

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

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            logger.info("Zone to modify the request");

            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                logger.info("Zone to modify the response");

                Optional.ofNullable(config.cookieValue).ifPresent(cookieVal -> {
                    exchange.getResponse()
                            .addCookie(ResponseCookie.from(config.cookieName, cookieVal).build());
                });
            }));
        };
    }

    @Override
    public String name() {
        return "ExampleCookie";
    }

    @Override
    public List shortcutFieldOrder() {
        return Arrays.asList("cookieName", "cookieValue");
    }

    public static class Config {
        private String cookieName;
        private String cookieValue;

        // Getters and Setters
        public String getCookieValue() { return cookieValue; }
        public void setCookieValue(String cookieValue) { this.cookieValue = cookieValue; }
        public String getCookieName() { return cookieName; }
        public void setCookieName(String cookieName) { this.cookieName = cookieName; }
    }
}

application.yml 中的使用方式

filters:
  - StripPrefix=2
  - ExampleCookie=user, myName

代码功能

  • 使用 YAML 文件中定义的值向响应添加一个 cookie。

约定与要求

  1. 类名必须以 FilterFactory 结尾。
  2. 需要继承 AbstractGatewayFilterFactory
  3. 内部的 Config 类用于存储从 YAML 文件传入的值。
  4. 过滤器逻辑位于 apply 方法中。
  5. name() 方法的返回值必须与 YAML 中使用的键匹配(或默认使用类名前缀)。
  6. shortcutFieldOrder 定义了短标记值映射到配置字段的顺序。

只有在 application.yml 中引用了此过滤器的路由才会应用它。

结论

您现在了解:

  • 什么是 Spring Cloud Gateway 以及它解决的问题。
  • 如何配置 predicates(谓词)和 filters(过滤器)以扩展其功能。
  • 如何创建 global filters(全局过滤器)和 custom filter factories(自定义过滤器工厂)以实现细粒度控制。

练习构建和定制网关,熟练掌握在实际项目中使用它们。

相关链接

Back to Blog

相关文章

阅读更多 »