Gateway 网关

把 Gateway 看成微服务系统的门卫,不处理订单,不计算价格,只处理请求进入系统之前的公共动作。

使用 Spring Cloud Gateway,可以通过 Java 配置路由:

@Configuration
public class EdgeRouteConfig {

    @Bean
    RouteLocator businessRoutes(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("order-entry", route -> route
                        .path("/api/orders/**")
                        .filters(filter -> filter
                                .stripPrefix(1)
                                .addRequestHeader("X-Edge-Source", "gateway"))
                        .uri("lb://order-service"))
                .route("member-entry", route -> route
                        .path("/api/members/**")
                        .filters(filter -> filter.stripPrefix(1))
                        .uri("lb://member-service"))
                .build();
    }
}

这里的 lb://order-service 不是写死某台机器的 IP,而是通过注册中心找到订单服务实例。订单服务扩成三台,网关可以把请求分发过去;某台实例下线,也不用通知客户端改地址。

@Component
@RequiredArgsConstructor
public class EdgeGuardFilter implements GlobalFilterOrdered {

    private final TokenInspector tokenInspector;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange,
                             GatewayFilterChain chain) {

        String path = exchange.getRequest().getURI().getPath();
        String traceId = Optional.ofNullable(
                        exchange.getRequest().getHeaders().getFirst("X-Trace-Id"))
                .filter(id -> !id.isBlank())
                .orElseGet(() -> UUID.randomUUID().toString().replace("-", ""));

        if (path.startsWith("/api/login")
                || path.startsWith("/api/public/")) {
            return chain.filter(withTrace(exchange, traceId));
        }

        String authorization = exchange.getRequest()
                .getHeaders()
                .getFirst(HttpHeaders.AUTHORIZATION);

        Optional<UserTicket> ticket = tokenInspector.inspect(authorization);
        if (ticket.isEmpty()) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }

        ServerHttpRequest request = exchange.getRequest()
                .mutate()
                .headers(headers -> {
                    headers.remove("X-User-Id");
                    headers.set("X-User-Id", ticket.get().userId());
                    headers.set("X-Trace-Id", traceId);
                })
                .build();

        return chain.filter(exchange.mutate().request(request).build());
    }

    private ServerWebExchange withTrace(ServerWebExchange exchange,
                                        String traceId) {
        ServerHttpRequest request = exchange.getRequest()
                .mutate()
                .header("X-Trace-Id", traceId)
                .build();

        return exchange.mutate().request(request).build();
    }

    @Override
    public int getOrder() {
        return -100;
    }
}

posted @ 2026-07-14 21:48  KLAPT  阅读(5)  评论(0)    收藏  举报