Gateway 过滤器与动态路由
约 604 字大约 2 分钟
布欧-Lewyon
2026-05-15
首页 › Spring Cloud › 网关
全局过滤器
GlobalFilter 对所有路由生效,适合鉴权、日志、限流。
鉴权过滤器
@Component
@Order(-1)
public class AuthGlobalFilter implements GlobalFilter {
// 白名单路径
private static final List<String> WHITE_LIST = List.of(
"/api/users/login", "/api/users/register"
);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String path = request.getURI().getPath();
// 白名单放行
if (WHITE_LIST.contains(path)) {
return chain.filter(exchange);
}
// 检查 Token
String token = request.getHeaders().getFirst("Authorization");
if (token == null || !token.startsWith("Bearer ")) {
return unauthorized(exchange, "未登录");
}
// 验证 Token(调用 user-service 或 JWT 解析)
String userId = JwtUtil.parseToken(token.replace("Bearer ", ""));
if (userId == null) {
return unauthorized(exchange, "Token 无效");
}
// 将用户 ID 传递到下游服务
exchange.getAttributes().put("userId", userId);
ServerHttpRequest mutatedReq = request.mutate()
.header("X-User-Id", userId)
.build();
return chain.filter(exchange.mutate().request(mutatedReq).build());
}
private Mono<Void> unauthorized(ServerWebExchange exchange, String msg) {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.UNAUTHORIZED);
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
String body = "{\"code\":401,\"msg\":\"" + msg + "\"}";
DataBuffer buffer = response.bufferFactory()
.wrap(body.getBytes(StandardCharsets.UTF_8));
return response.writeWith(Mono.just(buffer));
}
}请求日志过滤器
@Component
@Order(0)
public class LoggingGlobalFilter implements GlobalFilter {
private static final Logger log = LoggerFactory.getLogger(LoggingGlobalFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
long start = System.currentTimeMillis();
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
ServerHttpResponse response = exchange.getResponse();
long duration = System.currentTimeMillis() - start;
log.info("[{}] {} -> {} ({}ms)",
request.getMethod(), request.getURI(),
response.getStatusCode(), duration);
}));
}
}自定义过滤器工厂
@Component
public class XForwardedForGatewayFilterFactory
extends AbstractNameValueGatewayFilterFactory {
@Override
public GatewayFilter apply(NameValueConfig config) {
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
String clientIp = request.getRemoteAddress() != null
? request.getRemoteAddress().getAddress().getHostAddress()
: "unknown";
ServerHttpRequest mutated = request.mutate()
.header(config.getName(), config.getValue() + ";" + clientIp)
.build();
return chain.filter(exchange.mutate().request(mutated).build());
};
}
}filters:
- XForwardedFor=X-Forwarded-For, gatewayNacos 动态路由
不重启网关即可动态修改路由规则。
spring:
cloud:
gateway:
discovery:
locator:
enabled: true # 自动发现路由(按服务名 /SERVICE-ID/** 路由)
lower-case-service-id: true动态路由控制器
@RestController
@RequestMapping("/api/admin/routes")
public class DynamicRouteController {
@Autowired
private RouteDefinitionWriter routeDefinitionWriter;
@Autowired
private ApplicationEventPublisher publisher;
// 添加路由
@PostMapping
public Mono<Void> create(@RequestBody RouteDefinition route) {
return routeDefinitionWriter.save(Mono.just(route))
.then(Mono.fromRunnable(() ->
publisher.publishEvent(new RefreshRoutesEvent(this))));
}
// 删除路由
@DeleteMapping("/{id}")
public Mono<Void> delete(@PathVariable String id) {
return routeDefinitionWriter.delete(Mono.just(id))
.then(Mono.fromRunnable(() ->
publisher.publishEvent(new RefreshRoutesEvent(this))));
}
}Gateway 限流
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/api/users/**
filters:
- name: RequestRateLimiter # 限流过滤器
args:
redis-rate-limiter:
replenishRate: 10 # 令牌每秒填充数
burstCapacity: 20 # 令牌桶容量
key-resolver: "#{@ipKeyResolver}" # 限流 Key 解析器@Bean
public KeyResolver ipKeyResolver() {
return exchange -> {
String ip = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
return Mono.just(ip);
};
}小结
GlobalFilter全局生效:鉴权、日志、CORS。GatewayFilterFactory针对特定路由:限流、路径重写。- Nacos 实现动态路由:不重启网关增删路由。
- RequestRateLimiter + Redis 实现分布式限流。
- 过滤器执行顺序:
@Order越小优先级越高。
