SpringCloud 微服务架构与 Gateway
https://github.com/WuSangui571/cloud-demo 中的 README.md 文件浏览,此处发表的是经由 AI 润色过的精简版。
1. Gateway 概述
在包含订单、商品、支付、物流等多个微服务实例的业务场景中,前端需记忆众多服务地址。为简化管理,引入 Gateway 作为所有服务的统一入口。前端只需访问网关地址,网关根据请求路径通过服务注册与发现机制(例如 Nacos)转发至目标微服务。

2. 路由配置
2.1 需求与实现
需求:
/api/order/**路由至service-order。/api/product/**路由至service-product。实现负载均衡。
2.2 配置步骤
创建 Gateway 模块:
在
service和model同级目录下新建gateway模块。
添加依赖:
<!-- 网关依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- Nacos 注册中心 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 负载均衡 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>编写主入口程序:
package com.sangui.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* @author sangui
* @createTime 2025-09-28
* @description Gateway 主入口程序
* @version 1.0
*/
public class GatewayMainApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayMainApplication.class, args);
}
}配置基础信息:
spring
application
namegateway
cloud
nacos
server-addr127.0.0.18848
server
port80定义路由规则:
在
application.yaml或独立application-route.yaml中配置:
spring
cloud
gateway
routes
idorder-route
urilb//service-order
predicates
Path=/api/order/**
order1
idproduct-route
urilb//service-product
predicates
Path=/api/product/**
order2
idbing-route
urihttps//cn.bing.com
predicates
Path=/**
order999
profiles
includeroute调整服务路径:
修改
service-order和service-product的 Controller 添加前缀:
package com.sangui.order.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
("/api/order")
public class OrderController {
("/writeDb")
public String writeDb() {
return "writeDb success";
}
}package com.sangui.product.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
("/api/product")
public class ProductController {
("/product/{id}")
public Product getProduct(("id") Long productId) {
return new Product();
}
}注意:Feign 客户端需逐一调整路径,例如:
package com.sangui.order.feign;
import com.sangui.product.bean.Product;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
(value = "service-product", fallback = ProductFeignClientFallback.class)
public interface ProductFeignClient {
("/api/product/product/{productId}")
Product getProductById(("productId") Long productId);
}验证:
访问
http://localhost:80/api/order/create?userId=1&productId=2,实现负载均衡路由。
3. 断言配置
3.1 断言类型
Gateway 使用
RoutePredicateFactory实现断言,支持多种类型:
| 名称 | 参数(个数/类型) | 作用 |
|---|---|---|
| After | 1/datetime | 指定时间之后 |
| Before | 1/datetime | 指定时间之前 |
| Between | 2/datetime | 指定时间区间 |
| Cookie | 2/string,regexp | 匹配 Cookie 值 |
| Header | 2/string,regexp | 匹配请求头值 |
| Host | N/string | 匹配 Host 值 |
| Method | N/string | 匹配请求方法 |
| Path | 2/List<String>,bool | 匹配路径,支持尾部 / |
| Query | 2/string,regexp | 匹配请求参数 |
| RemoteAddr | 1/List<String> | 匹配请求来源(CIDR) |
| Weight | 2/string,int | 按权重负载均衡 |
| XForwardedRemoteAddr | 1/List<String> | 匹配 X-Forwarded-For 来源 |
3.2 断言写法
完整写法:
spring
cloud
gateway
routes
idorder-route
urilb//service-order
predicates
namePath
args
patterns/api/order/**
matchTrailingSlashtrue简写:
predicates:
- Path=/api/order/**3.3 自定义断言
示例:定义
Vip断言,匹配user=sangui参数。
package com.sangui.gateway.predicate;
import jakarta.validation.constraints.NotEmpty;
import lombok.Getter;
import lombok.Setter;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.GatewayPredicate;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import java.util.List;
import java.util.function.Predicate;
/**
* @author sangui
* @createTime 2025-09-28
* @description 自定义 Vip 断言工厂
* @version 1.0
*/
@Component
public class VipRoutePredicateFactory extends AbstractRoutePredicateFactory<VipRoutePredicateFactory.Config> {
public VipRoutePredicateFactory() {
super(Config.class);
}
@Override
public List<String> shortcutFieldOrder() {
return List.of("param", "value");
}
@Override
public Predicate<ServerWebExchange> apply(Config config) {
return (GatewayPredicate) exchange -> {
String paramValue = exchange.getRequest().getQueryParams().getFirst(config.param);
return StringUtils.hasText(paramValue) && paramValue.equals(config.value);
};
}
@Validated
@Getter
@Setter
public static class Config {
@NotEmpty
private String param;
@NotEmpty
private String value;
}
}配置:
spring:
cloud:
gateway:
routes:
- id: bing-route
uri: https://cn.bing.com
predicates:
- Path=/search
- Query=q,haha
- Vip=user,sangui验证:访问
http://localhost/search?q=haha&user=sangui路由至 Bing。
4. 过滤器配置
4.1 路径重写
问题:若服务路径无
/api/order/前缀,访问/api/order/readDb会 404。解决方案:使用
RewritePath过滤器。
spring:
cloud:
gateway:
routes:
- id: order-route
uri: lb://service-order
predicates:
- Path=/api/order/**
filters:
- RewritePath=/api/order/?(?<segment>.*), /${segment}
- id: product-route
uri: lb://service-product
predicates:
- Path=/api/product/**
filters:
- RewritePath=/api/product/?(?<segment>.*), /${segment}验证:访问
http://localhost/api/order/writeDb成功。
4.2 自定义过滤器
添加响应头:
filters:
- RewritePath=/api/order/?(?<segment>.*), /${segment}
- AddResponseHeader=sangui, blog
默认过滤器:
spring:
cloud:
gateway:
default-filters:
- AddResponseHeader=sangui, blog
routes:
# ...全局过滤器:
示例:记录请求耗时。
package com.sangui.filter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* @author sangui
* @createTime 2025-09-29
* @description 记录请求耗时全局过滤器
* @version 1.0
*/
@Slf4j
@Component
public class RtGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
long start = System.currentTimeMillis();
log.info("请求 [{}] 开始,时间: {}", request.getURI(), start);
return chain.filter(exchange).doFinally(res -> {
long end = System.currentTimeMillis();
log.info("请求 [{}] 结束,耗时: {}ms", request.getURI(), end - start);
});
}
@Override
public int getOrder() {
return 0;
}
}自定义过滤器工厂:
示例:添加一次性令牌。
package com.sangui.gateway.filter;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractNameValueGatewayFilterFactory;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import java.util.UUID;
/**
* @author sangui
* @createTime 2025-09-29
* @description 一次性令牌自定义过滤器
* @version 1.0
*/
@Component
public class OnceTokenGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
@Override
public GatewayFilter apply(NameValueConfig config) {
return (exchange, chain) -> chain.filter(exchange).then(Mono.fromRunnable(() -> {
ServerHttpResponse response = exchange.getResponse();
String token = "uuid".equalsIgnoreCase(config.getValue()) ? UUID.randomUUID().toString() : "Test Token";
response.getHeaders().add(config.getName(), token);
}));
}
}配置:
spring:
cloud:
gateway:
routes:
- id: order-route
uri: lb://service-order
filters:
- OnceToken=X-Response-Token, uuid
5. 全局跨域配置
单体服务:使用
@CrossOrigin或配置CorsFilterBean。微服务:通过 Gateway 配置:
spring
cloud
gateway
globalcors
cors-configurations
'[/**]'
allowed-origin-patterns'*'
allowed-headers'*'
allowedMethods'*'- 微信
- 赶快加我聊天吧

- 赶快加我聊天吧
