Gateway的路由谓词工厂
相关概念(术语)
- 路由 (Route): 路由是网关的基础构建模块,它是有ID,目标URI,谓词集合和过滤器集合定义。如果聚合谓词为true,则匹配路由。
- 谓词 (Predicate): 这是Java8的函数谓词,输入类型是Spring Framework
ServerWebExchange
, 这使得开发者可以匹配HTTP请求中的所有内容,例如 header 和 参数。 - 过滤器 (Filter): 这些是使用特定工厂构建的SpringFramework
GatewayFilter
实例。在此,可以在发送下游请求之前或之后修改请求和响应。
路由谓词工厂
SpringCloudGateway 将路由作为 Spring WebFlux HandlerMapping
基础架构的一部分进行匹配。SpringCloudGateway 包括许多内置的Route Predicate factory。所有这些谓词都与HTTP请求的不同属性匹配。多个Route Predicate工厂可以合并,也可以通过逻辑合并 and
。
1. After 路由谓词
After Route Predicate Factory 采用一个参数,即日期时间。该谓词匹配在当前日期时间之后发生的请求。
2. Before 路由谓词
Before Route Predicate Factory 采用一个参数,即日期时间。该谓词匹配在当前日期时间之前发生的请求。
3. Between 路由谓词
Between Route Predicate Factory 采用两个参数,都是日期时间类型的,该谓词匹配在两个日期之间发生的请求。
下面是统一的配置:
1 | spring: |
说明: 如果是时间之前的,使用Before
关键字。如果是时间之后的,使用After
关键字,如果要指明在两个日期之间,则使用Between
关键字,两个日期使用逗号隔开。[Asia/Shanghai]
表示使用的是以上海
为基准的时间。
4. Cookie 路由谓词
Cookie路由谓词工厂采用的是两个参数,一个是Cookie的名字,另外一个是合法的正则表达式。这个谓词用于匹配具有给定名称的Cookie,并且值匹配一个合法的正则表达式。
1 | spring: |
说明:这里是采用验证cookie的方式,当我们请求中携带了对应的正确的cookie信息,就可以访问成功到http://www.163.com
, 否则就会报 Not Found
.
下面是使用Postman测试的结果:
错误的cookie信息:
正确的cookie信息:
如果使用gateway时, 需要取出 cookie信息,可以使用下面的方法:
1 | "/resp") ( |
5. Header 路由谓词
Header 路由谓词工厂接受两个参数:header的name和其对应的合法的正则表达式值。只有在Header部分存在name并且其value也匹配的情况下,才能通过。
1 | spring: |
测试结果如下:
如果使用Gateway,需要从Header中取出信息,可以使用下面的方法:
1 | "/testHeader") (value = |
6. Host 路由谓词
Host(主机)路由谓词工厂,采用一个参数:主机名模式列表。该模式带有.
作为分隔符的Ant样式的模式,谓词与Host
匹配模式的Header部分。
1 | spring: |
这里为了更好的测试,我们单创建并启动一个服务,端口为8888的,大概代码如下:
1 | /** |
测试结果如下:
上面其实是将http://localhost:9999/user
映射到了 http://localhost:8888/user
上了。
注意:当然除了我们除了上面的写法,还有一些多样化的定制。同时也支持URI模板变量
1 | Host= www.ouyang.**, **.ouyang.**,**.ouyang.org |
7. Method 路由谓词
方法路由谓词工厂采用一个参数:用来匹配HTTP请求的类型。(GET,POST等).
1 | spring: |
以上需要匹配为POST
类型的请求才可以转发到 http://localhost:8888
上面,测试如下:
更改为POST
类型的请求:
8. Path 路由谓词
PathRoutePredicateFactory
需要PathMatcher
模式路径列表和一个可选的标志位参数matchOptionalTrailingSeparator
. 这是最常用的一个路由谓词。
1 | spring: |
这种使用路径来映射的方式。以上可以将http://localhost:9999/path
映射到http://localhost:8888/path
路径上,前一节也见过这个谓词,所以说这个谓词是最常用。还可以通过下面这个方式在请求路径上携带参数:(如果通过这种形式配置,在匹配命中进行路由的同时,会提取路径中对应的内容并且将键值对放在ServerWebExchange.getAttributes()
集合中,Key为ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE
, 这些提取出来的属性可以供GatewayFilter Factories
使用)。
1 | spring: |
另一个服务的接收:
1 | "/path") (value = |
9. Query 路由谓词
请求查询参数路由工厂QueryRoutePredicateFactory
需要一个必须的请求查询参数(Param的name)以及一个可选的正则表达式(regexp).
1 | spring: |
通过上述配置,我们的请求中只需要包含username
参数即可匹配路由。
1 | curl localhost:9999/testQuery?username=1 |
上面的测试可以通过,但是如果把username
删除或是改成别的,就无法匹配了。
还可以将Query参数以键值对的形式来配置,这样的请求过来的时候,不仅需要匹配名字,同时参数值需要与正则表达式匹配才能走路径。
1 | spring: |
以上匹配需要请求满足既有username
参数,并且值需要以ad
开头的长度为3的字符串才能匹配和路由。
测试如下:
1 | curl http://localhost:9999/testQuery?username=adv |
8888端口服务的controller方法为:
1 | "/testQuery") (value = |
10. RemoteAddr 路由谓词
RemoteAddrRoutePredicateFactory
匹配规则采用CIDR符号(IPv4或IPv6)字符串的列表(最小值为1),例如192.168.0.1/16(其中192.168.0.1是远程IP地址并且16是子网掩码)。
1 | spring: |
8888端口服务的处理方法:
1 | "/remote") (value = |
测试结果:
1 | curl http://127.0.0.1:9999/remote |
11. Weight 路由谓词
权重路由谓词工厂采用两个参数,分别为组(group)和权重(weight). 权重按组进行计算。
1 | spring: |
接受7777和8888请求的方法:
1 | //============port:7777 ============ |
测试结果如下: