Gateway过滤器
据作用范围划分为 GatewayFilter 和 GlobalFilter,区别如下:
GatewayFilter:网关过滤器,通过spring.cloud.routes.filters配置在具体路由下,只作用在当前路由上或通过spring.cloud.default-filters配置在全局,作用在所有路由上。GlobalFilter:全局过滤器,不需要在配置文件中配置,作用在所有的路由上,最终通过GatewayFilterAdapter包装成GatewayFilterChain可识别的过滤器,为请求业务以及路由的 URI 转换为真实业务服务请求地址的核心过滤器,不需要配置系统初始化时加载,并作用在每个路由上
Spring Cloud Gateway 的 Filter 的生命周期只有两个:“pre” 和 “post”。
- PRE: 过滤器在请求被路由之前调用。可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
- POST:过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的 HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
根据过滤器工厂的用途来划分,可以分为以下几种:Header、Parameter、Path、Body、Status、Session、Redirect、Retry、RateLimiter 和 Hystrix。
Path路由过滤器
Path 路径过滤器可以实现 URL 重写,通过重写 URL 可以实现隐藏实际路径提高安全性,易于用户记忆和键入,易于被搜索引擎收录等优点
RewritePath 网关过滤器工厂采用路径正则表达式参数和替换参数,使用 Java 正则表达式来灵活地重写请求路径
spring: application: name: gateway-server # 应用名称 cloud: gateway: # 路由规则 routes: - id: product-service # 路由 ID,唯一 uri: lb://product-service # lb:// 根据服务名称从注册中心获取服务请求地址 predicates: # 断言(判断条件) # 匹配对应 URI 的请求,将匹配到的请求追加在目标 URI 之后 - Path=/product/**, /api-gateway/** filters: # 网关过滤器 # 将 /api-gateway/product/1 重写为 /product/1 - RewritePath=/api-gateway(?<segment>/?.*), $\{segment}
PrefixPath 网关过滤器工厂为匹配的 URI 添加指定前缀
spring:
application:
name: gateway-server # 应用名称
cloud:
gateway:
# 路由规则
routes:
- id: product-service # 路由 ID,唯一
uri: lb://product-service # lb:// 根据服务名称从注册中心获取服务请求地址
predicates: # 断言(判断条件)
# 匹配对应 URI 的请求,将匹配到的请求追加在目标 URI 之后
- Path=/**
filters: # 网关过滤器
# 将 /1 重写为 /product/1
- PrefixPath=/product
StripPrefix 网关过滤器工厂采用一个参数 StripPrefix,该参数表示在将请求发送到下游之前从请求中剥离的路径个数
spring:
application:
name: gateway-server # 应用名称
cloud:
gateway:
# 路由规则
routes:
- id: product-service # 路由 ID,唯一
uri: lb://product-service # lb:// 根据服务名称从注册中心获取服务请求地址
predicates: # 断言(判断条件)
# 匹配对应 URI 的请求,将匹配到的请求追加在目标 URI 之后
- Path=/**
filters: # 网关过滤器
# 将 /api/123/product/1 重写为 /product/1
- StripPrefix=2
AddRequestParameter 网关过滤器工厂会将指定参数添加至匹配到的下游请求中
spring: application: name: gateway-server # 应用名称 cloud: gateway: # 路由规则 routes: - id: product-service # 路由 ID,唯一 uri: lb://product-service # lb:// 根据服务名称从注册中心获取服务请求地址 predicates: # 断言(判断条件) # 匹配对应 URI 的请求,将匹配到的请求追加在目标 URI 之后 - Path=/api-gateway/** filters: # 网关过滤器 # 将 /api-gateway/product/1 重写为 /product/1 - RewritePath=/api-gateway(?<segment>/?.*), $\{segment} # 在下游请求中添加 flag=1 - AddRequestParameter=flag, 1
自定义过滤器
在spring Cloud Gateway中,过滤器需要实现GatewayFilter和Ordered2个接口。写一个RequestTimeFilter,代码如下:
@Slf4j public class RequestTimeFilter implements GatewayFilter,Ordered { private final static String REQUEST_TIME_BEGIN="requestTimeBegin"; @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { exchange.getAttributes().put(REQUEST_TIME_BEGIN,System.currentTimeMillis()); return chain.filter(exchange).then(Mono.fromRunnable(()->{ Long startTime = exchange.getAttribute(REQUEST_TIME_BEGIN); if(startTime!=null){ log.info(exchange.getRequest().getURI().getRawPath()+":"+(System.currentTimeMillis()-startTime)+"ms"); } })); } @Override public int getOrder() { return 0; } }
Ordered中的int getOrder()方法是来给过滤器设定优先级别的,值越大则优先级越低。还有一个filterI(exchange,chain)方法,在该方法中,先记录了请求的开始时间,并保存在ServerWebExchange中,此处是一个“pre”类型的过滤器,然后再chain.filter的内部类中的run()方法中相当于"post"过滤器,在此处打印了请求所消耗的时间。然后将该过滤器注册到router中,代码如下:
@Bean public RouteLocator customerRouteLocator(RouteLocatorBuilder builder) { return builder.routes() .route(r -> r.path("/movie/**") .filters(f->f.hystrix(config -> config.setName("movie.service") .setFallbackUri("forward:/movie/fallback")) .filter(new RequestTimeFilter())) .uri(uri)).build(); }
global filter
GlobalFilter : 全局过滤器,不需要在配置文件中配置,作用在所有的路由上,最终通过GatewayFilterAdapter包装成GatewayFilterChain可识别的过滤器,为请求业务以及路由的URI转换为真实业务服务的请求地址的核心过滤器,不需要配置,系统初始化时加载,并作用在每个路由上。

该GlobalFilter会校验请求中是否包含了请求参数“token”,如何不包含请求参数“token”则不转发路由,否则执行正常的逻辑。代码如下:
@Slf4j public class TokenFilter implements GlobalFilter,Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { String token = exchange.getRequest().getQueryParams().getFirst("token"); if(StringUtils.isEmpty(token)){ log.info("token is empty..."); exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); } return chain.filter(exchange); } @Override public int getOrder() { return -100; } }
TokenFilter需要实现GlobalFilter和Ordered接口,然后根据ServerWebExchange获取ServerHttpRequest,然后根据ServerHttpRequest中是否含有参数token,如果没有则完成请求,终止转发,否则执行正常的逻辑。
需要将TokenFilter在工程的启动类中注入到Spring Ioc容器中,代码如下:
@Bean public TokenFilter tokenFilter(){ return new TokenFilter(); }
参考:
https://blog.csdn.net/forezp/article/details/85057268
https://windmt.com/2018/05/08/spring-cloud-14-spring-cloud-gateway-filter/
浙公网安备 33010602011771号