开发者指南 (Developer Guide)
本指南介绍了如何编写网关的一些自定义组件。
1. 编写自定义路由断言工厂 (Route Predicate Factories)
要编写自定义路由断言,你需要将 RoutePredicateFactory 实现为一个 Bean。通常建议继承抽象类 AbstractRoutePredicateFactory。
MyRoutePredicateFactory.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 (前置过滤器)
@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 (后置过滤器)
@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。该过滤器将应用于所有请求。
以下示例展示了如何分别设置全局的前置和后置过滤器:
@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 中,ServerWebExchange 和 ServerHttpRequest 都是不可变的。你不能直接调用 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。