过滤器工厂
过滤器种类
GatewayFilter是网关中提供的一种过滤器,可以对进入网关的请求和微服务响应的结果
做加工处理
Spring提供了31中不同的路由过滤器工厂
AddResponseHeader
表示给请求添加响应头
yaml
default-filters: # 默认过滤器
- AddResponseHeader=X-Response-Default-Red, Default-Blue # 添加响应头X-Response-Default-Red: Default-Blue
PrefixPath
表示给请求添加路径前缀
yaml
default-filters: # 默认过滤器
- PrefixPath=/httpbin
AddRequestHeader
表示给请求添加key为X-Request-red,value为blue的请求头,可以应用于流量染色
yaml
filters: # 服务过滤器
- AddRequestHeader=X-Request-red, blue # 添加请求头X-Request-red: blue
AddRequestHeadersIfNotPresent
表示给请求添加请求头,但只有当请求头里没有对应的请求头时才会添加,如果有则会传递原始的请求头
yaml
filters:
# 添加多个请求头X-Request-Color-1:blue,X-Request-Color-2:green
- AddRequestHeadersIfNotPresent=X-Request-Color-1:blue,X-Request-Color-2:green
AddRequestParameter表示
给请求添加请求参数
yaml
filters:
- AddRequestParameter=red, blue # 添加请求参数red=blue
AddResponseHeader
表示给请求添加响应头
yaml
filters:
- AddResponseHeader=X-Response-Red, Blue # 给请求添加响应头X-Response-Red: Blue
CircuitBreaker(断路器)
用于给接口做降级,当接口报错时降级去请求另一个接口
- 在使用断路器之前,需要先引入
spring-cloud-starter-circuitbreaker-reactor-resilience4j
依赖
yaml
spring:
cloud:
gateway:
routes:
- id: circuitbreaker_route
uri: lb://backing-service:8088
predicates:
- Path=/consumingServiceEndpoint
filters:
- name: CircuitBreaker
args:
name: myCircuitBreaker
fallbackUri: forward:/inCaseOfFailureUseThis
- RewritePath=/consumingServiceEndpoint, /backingServiceEndpoint
RequestRateLimiter
表示使用Redis做限流,使用的令牌桶算法如漏桶算法RedisLimitHandler
yaml
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
redis-rate-limiter.requestedTokens: 1
RedirectTo
根据请求头里包含的状态码重定向到某个地址
yaml
spring:
cloud:
gateway:
routes:
- id: prefixpath_route
uri: https://example.org
filters:
- RedirectTo=302, https://acme.org # 当请求头里包含302的状态码时重定向到该地址
RemoveRequestHeader
表示删除请求中对应的请求头
yaml
filters:
- RemoveRequestHeader=X-Request-Foo
RemoveRequestParameter
表示删除请求中对应的请求参数
yaml
filters:
- RemoveRequestParameter=red
RemoveResponseHeader
表示删除响应中对应的响应头
yaml
filters:
- RemoveResponseHeader=X-Response-Foo
RequestHeaderSize
表示限制请求的请求头大小
yaml
filters:
- RequestHeaderSize=1000B # 如果请求头超过1000B,则会发送431状态码
网关三大过滤器
路由过滤器
需求: 给所有进入userservice服务
的请求都添加一个请求头如Truth=Hello World!
,当前过滤器写在userservice服务
下因此仅对当前路由的请求生效
yaml
server:
port: 10010 # 网关端口
spring:
application:
name: gateway # 服务名称
cloud:
nacos:
server-addr: localhost:80 # nacos地址
gateway:
routes: # 网关路由配置
- id: user-service
uri: lb://userservice # 配置userservice服务的路由规则
predicates:
- Path=/user/**
filters:
- AddRequestHeader=Truth,Hello World! # 添加请求头Truth,值是Hello World!
在UserController中编写对应的控制器方法获取请求头信息,重启网关服务和userservice服务
并访问http://localhost:10010/user/test
java
@GetMapping("/test")
public void test(@RequestHeader("Truth") String tmp) {
System.out.println(tmp);
}
默认过滤器
默认过滤器
: 如果希望过滤器的操作对所有的路由都生效,则可以将过滤器工厂写到spring.cloud.gateway.default-filters属性
下
yaml
server:
port: 10010 # 网关端口
spring:
application:
name: gateway # 服务名称
cloud:
nacos:
server-addr: localhost:80 # nacos地址
gateway:
routes:
- id: user-service
uri: lb://userservice
predicates:
- Path=/user/**
default-filters: # 默认过滤器,对所有的路由请求都生效
- AddRequestHeader=Truth,Hello World!
全局过滤器
全局过滤器和GatewayFilter一样都可以对进入网关的请求和微服务的响应做加工处理
GatewayFilter网关过滤器
: 通过配置文件定义所以处理的逻辑是固定的且只有默认过滤器对所有路由请求生效GlobalFilter全局过滤器
: 可以编写代码做自己的业务逻辑,如登录状态判断,权限校验,请求限流
等,对所有的路由请求都生效
java
public interface GlobalFilter {
/**
* 处理当前请求,有必要的话通过{@link GatewayFilterChain}将请求交给下一个过滤器处理
*
* @param exchange 请求上下文,里面可以获取Request、Response等信息
* @param chain 用来把请求委托给下一个过滤器
* @return {@code Mono<Void>} 返回标示当前过滤器业务结束
*/
Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}
需求: 定义全局过滤器拦截请求,判断请求参数中是否有authorization且参数值是否为admin
, 如果同时满足则放行请求否则拦截
第一步: 在gateway模块
下新建cn.itcast.gateway.filter
包,然后编写AuthorizationFilter类
实现GlobalFilter接口
并重写其中的filter
方法
java
@Order(-1)
@Component
public class AuthorizationFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 1. 获取请求参数
ServerHttpRequest request = exchange.getRequest();
MultiValueMap<String, String> params = request.getQueryParams();
// 2. 获取authorization参数的值
String authorization = params.getFirst("authorization");
// 3. 校验
if ("admin".equals(authorization)) {
// 4. 满足需求则放行
return chain.filter(exchange);
}
// 拦截请求
// 5.1 先设置状态码,这里的常量底层就是401(在restFul中401表示未登录)
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
// 5.2 拦截请求
return exchange.getResponse().setComplete();
}
}
第二步: 重启网关测试我们的全局过滤器是否生效,只有访问http://localhost:10010/user/1?authorization=admin时可以看到正常数据
json
{
"id": 1,
"username": "柳岩",
"address": "湖南省衡阳市"
}
过滤器执行顺序
请求进入网关后会经过路由过滤器,DefaultFilter,GlobalFilter
三类过滤器,它们本质都是GatewayFilter
(GlobalFilter被封装在GatewayFilterAdapter中)
- 请求路由后会将
当前路由过滤器,DefaultFilter,GlobalFilter
合并到一个过滤器链集合中,在集合中根据order值对每个过滤器排序后依次按顺序执行
过滤器必须指定一个int类型的order值,order值越小优先级越高
即执行顺序越靠前(默认值为int最大值2147483647)
路由过滤器和de默认过滤器的order值
: 由Spring指定默认是按照声明顺序从1递增
全局过滤器的order值
: 通过实现Ordered接口实现getOrder()方法
或者添加@Order注解
来指定order值
java
//@Order(-1)
@Component
public class AuthorizationFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 1. 获取请求参数
MultiValueMap<String, String> params = exchange.getRequest().getQueryParams();
// 2. 获取authorization参数
String authorization = params.getFirst("authorization");
// 3. 校验
if ("admin".equals(authorization)) {
// 4. 满足需求则放行
return chain.filter(exchange);
}
// 5. 不满足需求,设置状态码,这里的常量底层就是401,在restFul中401表示未登录
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
// 6. 结束处理
return exchange.getResponse().setComplete();
}
@Override
public int getOrder() {
return -1;
}
}
过滤器的order值相同
: 按照defaultFilter > routeFilter > GlobalFilter
的顺序执行
- org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#
getFilters()方法
: 负责加载defaultFilters然后再加载某个路由过滤器最后合并 - org.springframework.cloud.gateway.handler.FilteringWebHandler#
handle()方法
: 负责加载全局过滤器最后与路由过滤器和默认过滤器合并
yaml
# 配置路由过滤器和默认过滤器
server:
port: 10010 # 网关端口
spring:
application:
name: gateway # 服务名称
cloud:
nacos:
server-addr: localhost:80 # nacos地址
gateway:
routes:
- id: user-service
uri: lb://userservice
predicates:
- Path=/user/**
filters: # 路由过滤器默认是按照声明顺序从1递增
- AddRequestHeader=Truth,Hello World! # order值为1
- RemoveRequestHeader=X-Request-Foo # order值为2
default-filters: # 默认过滤器
- AddRequestHeader=Truth,Hello World! # order值为1
- RemoveRequestHeader=X-Request-Foo # order值为2
# 将自定义的全局过滤器的order也设定为1