外观
一句话答案
方式一:自定义 GlobalFilter(全局过滤器)
核心要点
方式一:自定义 GlobalFilter(全局过滤器)
最常见的场景:统一认证、日志记录。
java
@Component
@Order(-1) // 数值越小,优先级越高
public class AuthGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// ========== Pre Filter 逻辑(请求到达下游之前) ==========
ServerHttpRequest request = exchange.getRequest();
String token = request.getHeaders().getFirst("Authorization");
// 白名单路径放行
String path = request.getURI().getPath();
if (path.startsWith("/api/auth/login")) {
return chain.filter(exchange);
}
// Token 校验
if (token == null || !token.startsWith("Bearer ")) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
try {
Claims claims = JwtUtil.parseToken(token.substring(7));
// 将用户信息放入请求头,传递给下游服务
ServerHttpRequest mutatedRequest = request.mutate()
.header("X-User-Id", claims.getSubject())
.header("X-User-Role", claims.get("role", String.class))
.build();
return chain.filter(exchange.mutate().request(mutatedRequest).build())
.then(Mono.fromRunnable(() -> {
// ========== Post Filter 逻辑(下游响应返回之后) ==========
ServerHttpResponse response = exchange.getResponse();
log.info("请求完成: {} {} → {}", request.getMethod(),
path, response.getStatusCode());
}));
} catch (Exception e) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
}
@Override
public int getOrder() {
return -1;
}
}方式二:自定义 GatewayFilter(局部过滤器)
java
// 自定义过滤器工厂
@Component
public class RequestTimingGatewayFilterFactory
extends AbstractGatewayFilterFactory<RequestTimingGatewayFilterFactory.Config> {
public RequestTimingGatewayFilterFactory() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
long startTime = System.currentTimeMillis();
exchange.getAttributes().put("startTime", startTime);
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
long duration = System.currentTimeMillis() - startTime;
if (duration > config.getSlowThreshold()) {
log.warn("慢请求: {} 耗时 {}ms",
exchange.getRequest().getURI(), duration);
}
}));
};
}
@Data
public static class Config {
private long slowThreshold = 1000; // 默认 1 秒
}
}yaml
# 在路由配置中使用
filters:
- name: RequestTiming
args:
slowThreshold: 2000Pre / Post 过滤器执行顺序示意:
请求 → [Global Pre -1] → [Global Pre 0] → [Route Pre 1]
→ 转发到下游服务 →
响应 ← [Route Post 1] ← [Global Post 0] ← [Global Post -1]三、负载均衡与通信
追问与易错
追问方向:
- Gateway 和 Zuul 区别?
- Gateway 限流怎么做?
- Gateway 怎么实现灰度?
易错点:
- ❌ Gateway 和 Nginx 一样——职责不同
- ❌ Gateway 性能不如 Nginx——职责不同不可比
💡 记忆锚点
Gateway像小区门卫:所有请求先过门卫(网关),门卫负责查身份证(认证GlobalFilter)、记出入登记(日志)、控制人流(限流)。过滤器链分Pre(请求到达前处理)和Post(响应返回后处理),GlobalFilter全局生效,GatewayFilter局部路由生效,Order值越小优先级越高。