Skip to content

开发者指南 (Developer Guide)

本指南介绍了如何编写网关的一些自定义组件。

1. 编写自定义路由断言工厂 (Route Predicate Factories)

要编写自定义路由断言,你需要将 RoutePredicateFactory 实现为一个 Bean。通常建议继承抽象类 AbstractRoutePredicateFactory

MyRoutePredicateFactory.java

java
@Component
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config> {

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

    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        // 从 Config 对象中获取配置参数
        return exchange -> {
            // 获取请求对象
            ServerHttpRequest request = exchange.getRequest();
            // 根据请求信息判断是否匹配配置条件
            return matches(config, request);
        };
    }

    public static class Config {
        // 在此处定义断言所需的配置属性
    }

}

2. 编写自定义网关过滤器工厂 (GatewayFilter Factories)

要编写自定义 GatewayFilter,你必须将 GatewayFilterFactory 实现为一个 Bean。通常建议继承抽象类 AbstractGatewayFilterFactory

以下示例展示了如何创建“前置(Pre)”和“后置(Post)”过滤器:

示例 1. PreGatewayFilterFactory.java (前置过滤器)

java
@Component
public class PreGatewayFilterFactory extends AbstractGatewayFilterFactory<PreGatewayFilterFactory.Config> {

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

	@Override
	public GatewayFilter apply(Config config) {
		// 从 Config 对象中获取配置信息
		return (exchange, chain) -> {
			// 如果你想构建一个 "pre" 过滤器,你需要在调用 chain.filter 之前修改请求
			ServerHttpRequest.Builder builder = exchange.getRequest().mutate();
			// 使用 builder 修改请求(例如添加 Header)
			return chain.filter(exchange.mutate().request(builder.build()).build());
		};
	}

	public static class Config {
		// 在此处定义过滤器所需的配置属性
	}
}

示例 2. PostGatewayFilterFactory.java (后置过滤器)

java
@Component
public class PostGatewayFilterFactory extends AbstractGatewayFilterFactory<PostGatewayFilterFactory.Config> {

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

	@Override
	public GatewayFilter apply(Config config) {
		// 从 Config 对象中获取配置信息
		return (exchange, chain) -> {
			return chain.filter(exchange).then(Mono.fromRunnable(() -> {
				ServerHttpResponse response = exchange.getResponse();
				// 在此处对响应进行一些操作(例如修改状态码或添加响应头)
			}));
		};
	}

	public static class Config {
		// 在此处定义过滤器所需的配置属性
	}
}

自定义过滤器的命名约定

自定义过滤器的类名应以 GatewayFilterFactory 结尾。

例如,如果你想在配置文件中使用名为 Something 的过滤器,那么对应的 Java 类必须命名为 SomethingGatewayFilterFactory

警告

虽然你可以创建一个不带 GatewayFilterFactory 后缀的类(例如 class AnotherThing),并在配置文件中通过 AnotherThing 引用它,但这不符合官方支持的命名规范,这种语法可能在未来的版本中被移除。请务必遵守此命名约定。

3. 编写自定义全局过滤器 (Global Filters)

要编写自定义全局过滤器,你必须将 GlobalFilter 接口实现为一个 Bean。该过滤器将应用于所有请求。

以下示例展示了如何分别设置全局的前置和后置过滤器:

java
@Bean
public GlobalFilter customGlobalFilter() {
    return (exchange, chain) -> exchange.getPrincipal()
        .map(Principal::getName)
        .defaultIfEmpty("Default User")
        .map(userName -> {
          // 在转发的请求中添加 Header
          ServerHttpRequest.Builder builder = exchange.getRequest().mutate().header("CUSTOM-REQUEST-HEADER", userName);
          // 构造新的 exchange 并继续执行
          return exchange.mutate().request(builder.build()).build();
        })
        .flatMap(chain::filter);
}

@Bean
public GlobalFilter customGlobalPostFilter() {
    return (exchange, chain) -> chain.filter(exchange)
        .then(Mono.just(exchange))
        .map(serverWebExchange -> {
          // 在响应中添加 Header
          serverWebExchange.getResponse().getHeaders().set("CUSTOM-RESPONSE-HEADER",
              HttpStatus.OK.equals(serverWebExchange.getResponse().getStatusCode()) ? "It worked": "It did not work");
          return serverWebExchange;
        })
        .then();
}

补充教学 —— 掌握网关开发的“响应式思维”

在编写自定义组件时,由于底层是 Project Reactor (WebFlux),你需要从传统的阻塞式编程切换到响应式编程。

1. 不可变性与 mutate()

在 WebFlux 中,ServerWebExchangeServerHttpRequest 都是不可变的。你不能直接调用 request.setHeader(...)

  • 模式:先调用 .mutate() 获取一个 Builder,修改后生成新的对象,再通过 exchange.mutate().request(newRequest).build() 传递下去。

2. 前置 (Pre) vs 后置 (Post)

  • Pre (前置):逻辑写在 chain.filter(exchange) 之前
  • Post (后置):逻辑写在 chain.filter(exchange) 之后。通常使用 .then().doFinally() 或在 .flatMap() 之后进行链式调用。

3. 过滤器工厂 (GatewayFilterFactory) vs 全局过滤器 (GlobalFilter)

  • GatewayFilterFactory
    • 作用域:精确控制。只有配置了该过滤器的路由才会生效。
    • 特点:可以接收参数(通过 Config 内部类)。
    • 场景:根据业务需要,给某些接口加限流,某些加灰度。
  • GlobalFilter
    • 作用域:全量覆盖。网关中所有的路由请求都会经过它。
    • 特点:通常没有复杂的参数配置。
    • 场景:全站统一的鉴权、全局耗时统计、审计日志、分布式链路追踪(TraceID 注入)。

4. 执行顺序 (Order)

  • 你可以通过实现 Ordered 接口或使用 @Order 注解来控制多个过滤器的执行顺序。
  • 数字越小,前置逻辑越早执行,后置逻辑越晚执行(类似于剥洋葱)。

建议: 初学者建议先从 GlobalFilter 练手,因为它最简单。只有当你需要为不同路由配置不同参数时,再考虑编写 GatewayFilterFactory

Based on Spring Framework.