过滤器的概念这里不展开说,简而言之就是在路由的过程中为了做一些逻辑,Gateway提供过滤器给开发者使用
Spring Cloud Gateway 过滤器根据作用范围划分为GatewayFilter和GlobalFilter,二者区别如下:
- GatewayFilter(网关过滤器):需要通过spring.cloud.routes.filters配置在具体的路由下,只作用在当前路由上或通过spring.cloud.default-filters配置在全局,作用在所有路由上
- GlobalFilter(全局过滤器):不需要在配置文件中配置,作用在所有路由上,最终通过GatewayFilterAdapter包装成GatewayFilterChain可识别的过滤器,它为请求业务以及路由的URI转换为真实业务服务请求地址的核心过滤器,不需要配置系统初始化时加载,作用于每个路由上
GatewayFilter(网关过滤器)
网关过滤器用于拦截并链式处理Web请求,可以实现横切与应用无关的需求,如:安全,访问超时的设置等。修改传入的HTTP请求或传出HTTP响应。Spring Cloud Gateway包含许多内置的网关过滤器工厂。一共有22个,包括头部过滤器,路径类过滤器,Hystrix过滤器和重写请求URL的过滤器,还有参数状态码等其他类型的过滤器。根据过滤器工厂的用途来划分可以划分为:Header,Parameter,Path,Body,Status,Session,Redirect,Retry,RateLimiter和Hystrix
-
Path路径过滤器
可以实现URL重写,通过重写URL可以实现隐藏实际路径,提高安全性,用于用户记忆和键入,易于被搜索引擎收录等优点。实现方式如下:
- 使用RewritePathGatewayFilterFactory
RewritePath网关过滤器工厂采用路径正则表达式参数和替换参数,使用Java正则表达式来灵活的重写请求路径
这里给出一个重写路径的例子:
server:
port: 8082
spring:
application:
name: service-gateway-server
cloud:
gateway:
#路由规则
routes:
- id: service-provider-gateway #路由ID,唯一
uri: lb://service-provider-gateway # lb:// 根据服务名称从注册中心获取服务请求地址
predicates: # 断言(判断条件)
- Path=/provider/**, /api-gateway/** # 匹配对应的URI的请求,将匹配到的请求追加在目标URI之后
# - Query=token #匹配请求参数中包含token的请求
#- Query=token,abc. #匹配请求参数中必须包含token,并且token的值满足正则 abc.
#- Method=GET #匹配GET方式
# 匹配中国上海时间 2020-02-02 20:20:20之后的请求
# - After=2020-02-02T20:20:20.000+08:00[Asia/Shanghai]
#- RemoteAddr=192.168.10.1/0 #0表示子网掩码
# 匹配请求头包含X-Request-Id 并且匹配正则表达式 \d+的请求
# - Header=X-Request-Id, \d+
filters:
# 将/api-gateway/provider/getProductsById/1 重写为 /provider/getProductsById/1
- RewritePath=/api-gateway(?<segment>/?.*),$\{segment}
为了方便演示,路由还按照旧的方式来配置,断言里的规则是,URL符合/provider/**, /api-gateway/**这样的路径就会被路由,而商品服务没有api-gateway/这个路径的资源,直接访问肯定会报错,我们通过重写路径将/api-gateway/的路径抹除
重启服务后测试,http://localhost:8082/api-gateway/provider/getProductsById/1 访问此路径正确返回结果
- 使用PrefixPathGatewayFilterFactory
使用PrefixPath来给每个匹配的URI增加指定前缀
server:
port: 8082
spring:
application:
name: service-gateway-server
cloud:
gateway:
#路由规则
routes:
- id: service-provider-gateway #路由ID,唯一
uri: lb://service-provider-gateway # lb:// 根据服务名称从注册中心获取服务请求地址
predicates: # 断言(判断条件)
- Path=/** # 匹配对应的URI的请求,将匹配到的请求追加在目标URI之后
# - Query=token #匹配请求参数中包含token的请求
#- Query=token,abc. #匹配请求参数中必须包含token,并且token的值满足正则 abc.
#- Method=GET #匹配GET方式
# 匹配中国上海时间 2020-02-02 20:20:20之后的请求
# - After=2020-02-02T20:20:20.000+08:00[Asia/Shanghai]
#- RemoteAddr=192.168.10.1/0 #0表示子网掩码
# 匹配请求头包含X-Request-Id 并且匹配正则表达式 \d+的请求
# - Header=X-Request-Id, \d+
filters:
# 将/api-gateway/provider/getProductsById/1 重写为 /provider/getProductsById/1
#- RewritePath=/api-gateway(?<segment>/?.*),$\{segment}
# 将getProductsById/1 重写为 /provider/getProductsById/1
- PrefixPath=/provider
为了方便测试,断言我改成了所有路径都符合,访问http://localhost:8082/getProductsById/1能够正常返回