Spring Cloud Gateway是Spring Cloud官方推出的第二代网关框架,旨在提供微服务简单、高效的API路由管理方式,以及基于过滤器实现安全认证、监控和限流等功能。另外,就是取代Netflix停止更新的网关组件Zuul。
Spring Cloud Gateway基于WebFlux + Netty + Reactor实现响应式API网关,摒弃传统Servlet容器,Netty构建提供断点服务。
01 核心概念
概念 | 内容 |
---|---|
路由(route) | 路由是网关中最基础部分,路由信息包括ID、URI、一组谓词、一组Filter组成。如果谓词为真,则说明请求URL与配置路由匹配。 |
谓词(predicates) | 也就是java.util.function.Predicate , Gateway使用Predicate实现路由匹配。 |
过滤器(Filter) | Gateway分为Gateway FilIer和Global Filter,用于处理请求和响应。 |
Spring Cloud Gateway路由就是请求转发规则,谓词就是匹配路径条件,过滤器修改路由请求以及响应提供业务处理逻辑。
02 基础案例
2.1 依赖
xml
<dependencies>
<!-- 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>
<!-- 排除web环境依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
需要排除spring-boot-starter-web
,也就是不用Servlet容器运行网关服务,否则会报错无法运行。

2.2 路由配置
yaml
spring:
application:
name: gateway
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
discovery:
locator:
## 是否开启微服务路由功能(默认false), 也就是通过微服务名称访问服务, 不建议打开
## 示例: http://localhost:13001/order/order/create
enabled: true
# 是否开启网关
enabled: true
如果开启微服务路由功能,支持通过http://localhost:13001/nx-order/order/create访问服务(nx-order)资源(/order/create),为了安全考虑不建议开启。
2.3 测试

03 路由谓词
路由谓词(Predicate)起到路由筛选匹配作用,Gateway默认提供很多谓词支持,包括路径谓词(Path)、时间谓词(After、Before、Between)、Cookie谓词(Cookie)、请求头谓词(Header)、域名谓词(Host)、请求方法谓词(Method)、路径谓词(Path)、请求参数谓词(Query)和远程地址谓词(RemoteAddr)。
3.1 路由配置
3.1.1 路由到指定URL
yaml
spring:
cloud:
gateway:
routes:
- id: {唯一标识}
uri: http://localhost:8001/
predicates:
- Path=/order/*
3.1.2 路由到注册中心微服务
yaml
spring:
cloud:
gateway:
routes:
- id: {唯一标识}
uri: lb://nx-order/
predicates:
- Path=/order/*
3.2 谓词工厂分类

谓词类别 | 谓词类 |
---|---|
时间谓词 | AfterRoutePredicateFactoryBeforeRoutePredicateFactoryBetweenRoutePredicateFactory |
Cookie谓词 | CookieRoutePredicateFactory |
请求头谓词 | HeaderRoutePredicateFactoryHostRoutePredicateFactory |
请求谓词 | MethodRoutePredicateFactoryPathRoutePredicateFactoryQueryRoutePredicateFactoryRemoteAddrRoutePredicateFactoryWeightRoutePredicateFactory |
3.2.1 After路由断言工厂
AfterRoutePredicateFactory需要配置UTC格式时间参数,请求时间与配置时间相比,若请求时间在参数时间之后,匹配成功,断言为true。
yaml
spring:
cloud:
gateway:
routes:
- id: after_route
uri: lb://nx-user
predicates:
# 当且仅当请求时间After配置时间, 才会转发到用户微服务, 否则不匹配返回404
# 例如: http://localhost:8040/users/1 -> nx-user/users/1
- After=2024-04-30T17:42:47.789-07:00[America/Denver]
3.2.2 Before路由断言工厂
BeforeRoutePredicateFactory需要配置UTC格式时间参数,请求时间与配置时间相比,若请求时间在参数时间之前,匹配成功,断言为true。
yaml
spring:
cloud:
gateway:
routes:
- id: before_route
uri: lb://nx-user
predicates:
# 当且仅当请求时间After配置时间, 才会转发到微服务, 否则不匹配返回404
# 例如: http://localhost:8040/users/1 -> nx-user/users/1
- After=2024-04-30T17:42:47.789-07:00[America/Denver]
yaml
spring:
cloud:
gateway:
routes:
- id: after_route
uri: lb://nx-user
predicates:
# 当且仅当请求时间Before配置时间, 才会转发到微服务, 否则不匹配返回404
# 例如: http://localhost:8040/users/1 -> nx-user/users/1
- Before=2024-04-30T17:42:47.789-07:00[America/Denver]
3.2.3 Between路由断言工厂
BetweenRoutePredicateFactory需要配置两个UTC格式时间参数,请求时间需要处于两个参数时间之间,匹配成功,断言为true。
yaml
spring:
cloud:
gateway:
routes:
- id: between_route
uri: lb://x-user
predicates:
# 当且仅当请求时间Between配置时间, 才会转发到微服务, 否则不匹配返回404
- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2027-01-21T17:42:47.789-07:00[America/Denver]
3.2.4 Cookie路由断言工厂
CookieRoutePredicateFactory包含两个参数,分别是cookie 的key与value。当请求携带指定key与value的Cookie时,匹配成功,断言为true。
yaml
spring:
cloud:
gateway:
routes:
- id: cookie_route
uri: lb://nx-user
predicates:
## cookie[domain=ch.p]
- Cookie=domain, ch.p
3.2.5 Header路由断言工厂
HeaderRoutePredicateFactory包含两个参数,分别是请求头header的key与value。当请求携带指定key与value的header时,匹配成功,断言为true。
yaml
spring:
cloud:
gateway:
routes:
- id: header_route
uri: lb://nx-user
predicates:
# 当且仅当携带请求头X-Request-Id, 并且值符合正则\d+时,才会转发到微服务
- Header=X-Request-Id, \d+
3.2.6 Host路由断言工厂
HostRoutePredicateFactory包含请求头Host属性。当请求携带指定Host属性值时,匹配成功,断言为true。
yaml
spring:
cloud:
gateway:
routes:
- id: host_route
uri: lb://nx-user
predicates:
# 当且仅当名请求头Host符合**.somehost.org或**.anotherhost.org时, 才会转发微服务
- Host=**.somehost.org,**.anotherhost.org
3.2.7 Method路由断言工厂
MethodRoutePredicateFactory用于判断请求是否使用指定请求方法,比如是POST、GET等。当请求中使用指定请求方法时,匹配成功,断言为true。
yaml
spring:
cloud:
gateway:
routes:
- id: method_route
uri: lb://nx-user
predicates:
# 当且仅当HTTP请求方法是GET时, 才会转发微服务
- Method=GET
3.2.8 Path路由断言工厂
PathRoutePredicateFactory用于判断请求路径是否包含指定URI。若包含匹配成功断言为true,此时会将匹配上URI拼接到要转向目标URI后面,形成统一URI。
yaml
spring:
cloud:
gateway:
routes:
- id: path_route
uri: lb://nx-user
predicates:
# 当且仅当访问路径是/users/*或者/some-path/**,才会转发微服务
- Path=/users/{segment},/some-path/**
3.2.9 Query路由断言工厂
QueryRoutePredicateFactory用于查找请求指定参数。其可以只查看参数名称,也可以同时查看参数名与参数值。当请求包含指定参数名或名值对匹配成功,断言为true。
yaml
spring:
cloud:
gateway:
routes:
- id: query_route
uri: lb://nx-user
predicates:
# 当且仅当请求带有baz的参数,才会转发到微服务
# eg. 访问http://localhost:8040/users/1?baz=xx -> nx-user/users/1?baz=xx
- Query=baz
yaml
spring:
cloud:
gateway:
routes:
- id: query_route
uri: lb://msb-user
predicates:
# 当且仅当请求带有名为foo参数, 且参数值符合正则ba., 才会转发到微服务
# eg. 访问http://localhost:8040/users/1?baz=baz -> nx-user/users/1?baz=baz
- Query=foo, ba.
3.2.10 RemoteAddr路由断言工厂
RemoteAddrRoutePredicateFactory用于判断访问IP地址是否在断言中指定IP范围。当访问目标IP在指定范围时,匹配成功,断言为true。
yaml
spring:
cloud:
gateway:
routes:
- id: remoteaddr_route
uri: lb://nx-user
predicates:
# 当且仅当请求IP是192.168.1.1/24网段, 例如192.168.1.10, 才会转发到用户微服务
# eg. 访问http://localhost:8040/users/1 -> nx-user/users/1
- RemoteAddr=192.168.1.1/24
如果Spring Cloud Gateway位于反向代理Nginx后面,获取到远程地址可能不正确,此时可以自定义RemoteAddressResolver
解决。
3.2.11 Weight路由断言工厂
WeightRoutePredicateFactory包含两个参数,分别表示组(group)与权重(weight)。对于同一组多个 URI地址,路由器会根据设置权重,按比例将请求转发给相应的URI实现负载均衡。
yaml
spring:
cloud:
gateway:
routes:
- id: weight_high
uri: https://weighthigh.org
predicates:
- Weight=group1, 8
- id: weight_low
uri: https://weightlow.org
predicates:
- Weight=group1, 2
3.3 自定义谓词
自定义谓词类命名必须以RoutePredicateFactory结尾,使用前缀进行配置。
java
@Data
public class CustomCfg {
private LocalTime start;
private LocalTime end;
}
@Component
public class CustomRoutePredicateFactory extends AbstractRoutePredicateFactory<CustomCfg> {
public TimeBetweenRoutePredicateFactory() {
super(TimeBetweenConfig.class);
}
@Override
public Predicate<ServerWebExchange> apply(TimeBetweenConfig config) {
LocalTime start = config.getStart();
LocalTime end = config.getEnd();
return new Predicate<ServerWebExchange>() {
@Override
public boolean test(ServerWebExchange serverWebExchange) {
LocalTime now = LocalTime.now();
return now.isAfter(start) && now.isBefore(end);
}
};
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("start","end");
}
}
yaml
spring:
cloud:
gateway:
routes:
- id: path_route
uri: lb://nx-user
predicates:
- Path=/order/*
- Custom=上午08:00, 下午11:00
04 过滤器工厂
Spring Cloud Gateway内置很多过滤器工厂(GatewayFilter Factories),使用过滤器工厂可以进行业务逻辑处理器,比如添加/剔除响应头,添加/去除参数等。
4.1 内置过滤器
4.1.1 AddRequestHeader
为原始请求添加名为X-Request-Foo=Bar请求头。
yaml
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: https://example.org
filters:
- AddRequestHeader=X-Request-Foo, Bar
4.1.2 AddRequestParameter
为原始请求添加请求参数foo=bar
yaml
spring:
cloud:
gateway:
routes:
- id: add_request_parameter_route
uri: https://example.org
filters:
- AddRequestParameter=foo, bar
4.1.3 AddResponseHeader
为处理添加X-Request-Foo=Bar响应头
yaml
spring:
cloud:
gateway:
routes:
- id: add_response_header_route
uri: https://example.org
filters:
- AddResponseHeader=X-Response-Foo, Bar
4.1.4 DedupeResponseHeader
Spring Cloud Greenwich SR2提供DedupeResponseHeader新特性,低于这个版本无法使用。可以阅读DedupeResponseHeaderGatewayFilterFactory
注释了解功能,比官方文档写得还好。
yaml
spring:
cloud:
gateway:
routes:
- id: dedupe_response_header_route
uri: https://example.org
filters:
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin, RETAIN_FIRST
如果Gateway、微服务设置CORS(跨域)请求头不做任何配置,那么通过请求 -> 网关 -> 微服务响应数据头数据就会重复。
yaml
Access-Control-Allow-Credentials: true, true
Access-Control-Allow-Origin: https://www.example.com, https://www.example.com
通过配置DedupeResponseHeader,就可以实现剔除重复响应数据值。
yaml
filters:
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
另外,去重Header如果有多个,可以使用空格分隔即可,去重策略包括RETAIN_FIRST、RETAIN_LAST和RETAIN_UNIQUE。
去重策略 | 内容 |
---|---|
RETAIN_FIRST | 默认值,保留第一个值 |
RETAIN_LAST | 保留最后一个值 |
RETAIN_UNIQUE | 保留所有唯一值,以第一次出现顺序保留 |
4.1.5 PrefixPath
为匹配路由添加前缀。例如:访问${GATEWAY_URL}/hello
会转发到https://example.org/mypath/hello
。
yaml
spring:
cloud:
gateway:
routes:
- id: prefixpath_route
uri: https://example.org
filters:
- PrefixPath=/mypath
4.1.6 PreserveHostHeader
如果没有设置,那么通过Http Client控制请求头Host。如果已设置,那么会额外设置一个请求属性(preserveHostHeader=true),路由过滤器会检查从而判断是否要发送原始请求头Host。
yaml
spring:
cloud:
gateway:
routes:
- id: preserve_host_route
uri: https://example.org
filters:
- PreserveHostHeader
4.1.7 RequestRateLimiter
yaml
spring:
cloud:
gateway:
routes:
- id: requestratelimiter_route
uri: https://example.org
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
4.1.8 RedirectTo
重定向过滤工厂配置格式RedirectTo=status, URL [, includeRequestParams]
,通过带有300系列请求头Location:URL
执行重定向,也可以指定重定向是否带有请求参数(未指定默认为false)。
yaml
spring:
cloud:
gateway:
routes:
- id: prefixpath_route
uri: https://example.org
filters:
# https://example.org?skip=10 => https://acme.org
- RedirectTo=302, http://www.acme.com, false
4.1.9 RemoveHopByHop
移除转发请求头,多个使用逗号(,
)分隔,能够移除请求头包括Connection、Keep-Alive、Proxy-Authenticate、Proxy-Authorization、TE、Trailer、Transfer-Encoding和Upgrade。
csharp
spring.cloud.gateway.filter.remove-hop-by-hop.headers: Connection,Keep-Alive
4.1.10 RemoveRequestHeader
yaml
spring:
cloud:
gateway:
routes:
- id: removerequestheader_route
uri: https://example.org
filters:
- RemoveRequestHeader=X-Request-Foo
4.1.11 RemoveResponseHeader
yaml
spring:
cloud:
gateway:
routes:
- id: removeresponseheader_route
uri: https://example.org
filters:
- RemoveResponseHeader=X-Response-Foo
4.1.12 RewritePath
重写请求路径,(?<segment>/?.*)
表示/?.*
匹配结果捕获到segment组,${segment}
表示置换segment分组文本到此处。
需要注意,$
是避免YAML语法认为此处为变量,网关解析时会被替换为${segment}。
正则规则 | 内容 |
---|---|
?<segment> | 规则组 |
? | 出现0次或者1次 |
.* | 任意字符出现0次或多次 |
yaml
spring:
cloud:
gateway:
routes:
- id: rewritepath_route
uri: https://example.org
predicates:
- Path=/foo/**
filters:
# http://gateway/foo/uml/index.html => https://example.org/uml/index.html
- RewritePath=/foo/(?<segment>.*), /${segment}
4.1.13 RewriteResponseHeader
下游请求头X-Response-Foo 值为user=ford&password=omg!what&flag=true
,将被重置为user=ford&password=***&flag=true
。需要注意,YAML规范必须使用$
来表示$
。
yaml
spring:
cloud:
gateway:
routes:
- id: rewriteresponseheader_route
uri: https://example.org
filters:
- RewriteResponseHeader=X-Response-Foo, password=[^&]+, password=***
4.1.14 SaveSession
请求转发后端微服务之前,强制执行WebSession::save
操作。用于Spring Session延迟数据存储,并希望请求转发前保存会话状态情况,比如集成使用Spring Secutiry与Spring Session传递会话信息给校友服务器。
yaml
spring:
cloud:
gateway:
routes:
- id: save_session
uri: https://example.org
predicates:
- Path=/foo/**
filters:
- SaveSession
4.1.15 SecureHeaders
添加一系列安全作用响应头,Spring Cloud Gateway主要参考博客为https://blog.appcanary.com/2017/http-security-headers.html
引入。
如果需要修改默认值,可以通过spring.cloud.gateway.filter.secure-headers.[请求头]=值
进行修改。另外,也可以使用spring.cloud.gateway.filter.secure-headers.disable=[请求头,...]
禁用配置。
默认请求头 | 请求头值 |
---|---|
X-Xss-Protection | mode=block |
Strict-Transport-Security | max-age=631138519 |
X-Frame-Options | DENY |
X-Content-Type-Options | nosniff |
Referrer-Policy | no-referrer |
Content-Security-Policy | default-src 'self' https:; font-src 'self' https: data:; img-src 'self' https: data:; object-src 'none'; script-src https:; style-src 'self' https: 'unsafe-inline' |
X-Download-Options | noope |
X-Permitted-Cross-Domain-Policie | none |
4.1.16 SetPath
通过请求路径片段模板化,达到操作修改路径目的。比如访问${GATEWAY_PATH}/foo/bar
,后端微服务路径修改为/bar
。
yaml
spring:
cloud:
gateway:
routes:
- id: setpath_route
uri: https://example.org
predicates:
- Path=/foo/{segment}
filters:
- SetPath=/{segment}
4.1.17 SetResponseHeader
yaml
spring:
cloud:
gateway:
routes:
- id: setresponseheader_route
uri: http://example.org
filters:
- SetResponseHeader=X-Response-Foo, Bar
如果后端服务响应带有名为 X-Response-Foo
的响应头,则将值改为替换成 Bar
。
4.1.18 SetStatus
修改响应的状态码,值可以是数字,也可以是字符串,但是状态值必须是Spring HttpStatus枚举类的值。
yaml
spring:
cloud:
gateway:
routes:
- id: setstatusstring_route
uri: http://example.org
filters:
- SetStatus=BAD_REQUEST
- id: setstatusint_route
uri: http://example.org
filters:
- SetStatus=401
4.1.19 StripPrefix
数字表示要截断路径数量。如果请求路径为/name/bar/foo
,则路径会修改为/foo
,也就是会截断至2个路径。
yaml
spring:
cloud:
gateway:
routes:
- id: nameRoot
uri: http://nameservice
predicates:
- Path=/name/**
filters:
- StripPrefix=2
4.1.20 Retry
针对不同响应做重试
参数 | 内容 |
---|---|
retries | 重试次数 |
statuses | 重试状态码,可选值查看org.springframework.http.HttpStatus |
methods | 重试请求方法,可选值查看org.springframework.http.HttpMethod |
series | HTTP状态码系列,可选值查看org.springframework.http.HttpStatus.Series |
yaml
spring:
cloud:
gateway:
routes:
- id: retry_test
uri: http://localhost:8080/flakey
predicates:
- Host=*.retry.com
filters:
- name: Retry
args:
retries: 3
statuses: BAD_GATEWAY
4.1.21 RequestSize
设置后端服务收到最大请求包大小,默认值为5M。如果请求超过设置值,返回413 Payload Too Large 。
yaml
spring:
cloud:
gateway:
routes:
- id: request_size_route
uri: http://localhost:8080/upload
predicates:
- Path=/upload
filters:
- name: RequestSize
args:
# 单位字节
maxSize: 5000000
4.1.22 默认过滤器工厂
yaml
spring:
cloud:
gateway:
default-filters:
- AddResponseHeader=X-Response-Default-Foo, Default-Bar
- PrefixPath=/httpbin
4.2 AddRequestHeader
断点打在org.springframework.cloud.gateway.filter.NettyRoutingFilter#filter
,就可以调试Gateway转发具体细节。

yaml
logging:
level:
org.springframework.cloud.gateway: trace
org.springframework.http.server.reactive: debug
org.springframework.web.reactive: debug
reactor.ipc.netty: debug

4.3 自定义过滤器工厂
Gateway底层基于Netty构建,封装请求和响应封装到ServerWebExchange,然后进行过滤器(GlobalFilter)拦截处理请求。
4.3.1 过滤器工厂定义
java
public interface GatewayFilter extends ShortcutConfigurable {
String NAME_KEY = "name";
String VALUE_KEY = "value";
Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}
核心API | 内容 |
---|---|
exchange.getRequest().mutate() | 修改请求 |
exchange.mutate() | 修改Exchange |
chain.filter(exchange) | 传递下一个过滤器处理 |
exchange.getResponse() | 获取响应 |
4.3.2 自定义过滤器工厂
自定义过滤器工厂可以继承AbstractGatewayFilterFactory,可以参考RequestSizeGatewayFilterFactory实现类。另外,AbstractNaeValueGatewayFilterFactory底层扩展实现AbstractGatewayFilterFactory,简化过滤器操作,主要参考类是AddRequestHeaderGatewayFilterFactory。
需要注意的是,必须以GatewayFilterFactory结尾定义过滤器工厂,配置文件才能被Gateway识别和操作。
java
@Slf4j
@Component
public class PrintLogGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
@Override
public GatewayFilter apply(NameValueConfig config) {
// 这里应用启动会执行两次, 需要放到方法里面
// log.info("request info={}:{}",config.getName(), config.getValue());
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("request info={}:{}",config.getName(),config.getValue());
// 获取请求进行修改
ServerHttpRequest modifiedRequest = exchange.getRequest().mutate().build();
// 设置请求值
// ServerHttpRequest modifiedRequest = exchange.getRequest().mutate()
// header(config.getName(), value).build();
ServerWebExchange modifiedExchange = exchange.mutate().request(modifiedRequest).build();
return chain.filter(modifiedExchange);
}
};
}
}
yaml
spring:
application:
name: nx-gateway
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
discovery:
locator:
enabled: false
enabled: true
routes:
- id: order-route
uri: lb://nx-order
predicates:
- Path=/order/*
filters:
- PrintLog=sex,man
4.4 全局过滤器
Spring Cloud Gateway组件GatewayFilter仅支持特定路由,如果需要全局过滤器可以配置GlobalFilter,可以参考文档docs.spring.io/spring-clou...。
4.4.1 LoadBalancerClientFilter
如果URL具有LB方案(例如lb://myservice),Gateway就会通过LoadBalancerClientFilter使用LoadBalancerClient
解析服务名称为实际主机与端口,并且缓存原始URL到请求 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
属性。
yaml
spring:
gateway:
routes:
- id: order-route
uri: lb://nx-order
predicates:
- Path=/order/*
java
public class LoadBalancerClientFilter implements GlobalFilter, Ordered {
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 获取请求地址
URI url = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR);
String schemePrefix = exchange.getAttribute(GATEWAY_SCHEME_PREFIX_ATTR);
// 非lb协议
if (url == null || (!"lb".equals(url.getScheme()) && !"lb".equals(schemePrefix))) {
return chain.filter(exchange);
}
addOriginalRequestUrl(exchange, url);
if (log.isTraceEnabled()) {
log.trace("LoadBalancerClientFilter url before: " + url);
}
// 负载均衡选择实例
final ServiceInstance instance = choose(exchange);
if (instance == null) {
throw NotFoundException.create(properties.isUse404(), ...);
}
URI uri = exchange.getRequest().getURI();
String overrideScheme = instance.isSecure() ? "https" : "http";
if (schemePrefix != null) {
overrideScheme = url.getScheme();
}
// 获取请求URI
URI requestUrl = loadBalancer.reconstructURI(
new DelegatingServiceInstance(instance, overrideScheme), uri);
exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl);
return chain.filter(exchange);
}
protected ServiceInstance choose(ServerWebExchange exchange) {
return loadBalancer.choose(
((URI) exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR)).getHost());
}
}
4.4.2 自定义全局过滤器
全局过滤器实现GlobalFilter接口,实现Order接口确定过滤器执行顺序,值越小越靠前处理。
java
@Slf4j
@Component
public class IPAddressStatisticsFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
InetSocketAddress host = exchange.getRequest().getHeaders().getHost();
if (host == null || host.getHostName() == null) {
exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
return exchange.getResponse().setComplete();
}
String hostName = host.getHostName();
AtomicInteger count = IpCache.CACHE.getOrDefault(hostName, new AtomicInteger(0));
count.incrementAndGet();
IpCache.CACHE.put(hostName, count);
log.info("ip = {}, request count={}", hostName, count.intValue());
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -1;
}
}