惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

W
WeLiveSecurity
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Hacker News - Newest:
Hacker News - Newest: "LLM"
Cloudbric
Cloudbric
V
Visual Studio Blog
L
LangChain Blog
A
About on SuperTechFans
B
Blog
T
Tenable Blog
罗磊的独立博客
Hacker News: Ask HN
Hacker News: Ask HN
Blog — PlanetScale
Blog — PlanetScale
博客园 - 三生石上(FineUI控件)
The Register - Security
The Register - Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
P
Palo Alto Networks Blog
U
Unit 42
WordPress大学
WordPress大学
D
Darknet – Hacking Tools, Hacker News & Cyber Security
N
News and Events Feed by Topic
T
Threat Research - Cisco Blogs
C
Check Point Blog
Security Latest
Security Latest
M
MIT News - Artificial intelligence
Application and Cybersecurity Blog
Application and Cybersecurity Blog
宝玉的分享
宝玉的分享
P
Proofpoint News Feed
NISL@THU
NISL@THU
Forbes - Security
Forbes - Security
S
Securelist
Security Archives - TechRepublic
Security Archives - TechRepublic
Hugging Face - Blog
Hugging Face - Blog
aimingoo的专栏
aimingoo的专栏
Latest news
Latest news
GbyAI
GbyAI
T
Troy Hunt's Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
L
LINUX DO - 热门话题
V2EX - 技术
V2EX - 技术
小众软件
小众软件
Google DeepMind News
Google DeepMind News
K
Kaspersky official blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
O
OpenAI News
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
N
Netflix TechBlog - Medium
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Google DeepMind News
Google DeepMind News
P
Proofpoint News Feed

博客园 - KLAPT

CodeX =>Skills Redis 内存满了怎么处理 SpringBoot 默认配置修改 JWT 续签 Access Token + Refresh Token 双 Token claudeCode 命令 MyBatis 的 Mapper 接口 AI | CC GUI 集成 IDEA 完整教程 在IDEA中使用Claude Code IDEA中使用CodeX MyBatisPlus解决大数据量查询慢问题 idea 中的 claude code Token Dubbo 和 Spring Cloud Gateway的区别 Transactional 注解中propagation 掌握 Spring 框架这 10 个扩展点 SpringBoot 快速实现 api 加密 Spring Boot/Cloud 中 bootstrap.yml 与 application.yml SpringBoot 实现 DOCX 转 PDF 微服务Token鉴权设计的几种方案 进程、线程、协程 RSA 加密 Java二维码 ntp服务端和客户端 Chronyd与NTP chronyd 作为服务器时钟 chrony sudo命令和su 的区别 java -cp 和 java -jar Maven 项目打包:实现业务代码与第三方依赖分离 达梦数据库创建用户 梦数据库新增大字段报错问题 达梦数据库操作 MySQL UPDATE多表关联更新 达梦数据库 为HTTP POST请求设置请求体 在Java中调用第三方接口并返回第三方页面 Java调用第三方接口的方法 Nginx 之Rewrite 使用详解 linux 命令 Spring Boot项目中集成Spring Security OAuth2和Apache Shiro
Gateway 网关
KLAPT · 2026-07-14 · via 博客园 - KLAPT

把 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;
    }
}