0
点赞
收藏
分享

微信扫一扫

Gateway的路由谓词工厂


Gateway的路由谓词工厂

文章目录

  • ​​Gateway的路由谓词工厂​​
  • ​​相关概念(术语)​​
  • ​​路由谓词工厂​​
  • ​​1. After 路由谓词​​
  • ​​2. Before 路由谓词​​
  • ​​3. Between 路由谓词​​
  • ​​4. Cookie 路由谓词​​
  • ​​5. Header 路由谓词​​
  • ​​6. Host 路由谓词​​
  • ​​7. Method 路由谓词​​
  • ​​8. Path 路由谓词​​
  • ​​9. Query 路由谓词​​
  • ​​10. RemoteAddr 路由谓词​​
  • ​​11. Weight 路由谓词​​

相关概念(术语)

  • 路由 (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​​ 。

Gateway的路由谓词工厂_正则表达式

1. After 路由谓词

After Route Predicate Factory 采用一个参数,即日期时间。该谓词匹配在当前日期时间之后发生的请求。

2. Before 路由谓词

Before Route Predicate Factory 采用一个参数,即日期时间。该谓词匹配在当前日期时间之前发生的请求。

3. Between 路由谓词

Between Route Predicate Factory 采用两个参数,都是日期时间类型的,该谓词匹配在两个日期之间发生的请求。

下面是统一的配置:

spring:
cloud:
gateway:
routes:
- id: gateway-service
uri: https://www.163.com
predicates:
# - Before= 2019-10-25T00:00:00+08:00[Asia/Shanghai]
# - After= 2019-10-25T00:00:00+08:00[Asia/Shanghai]
- Between= 2019-10-25T00:00:00+08:00[Asia/Shanghai],2019-10-25T18:05:00+08:00[Asia/Shanghai]

说明: 如果是时间之前的,使用​​Before​​​关键字。如果是时间之后的,使用​​After​​​关键字,如果要指明在两个日期之间,则使用​​Between​​​ 关键字,两个日期使用逗号隔开。​​[Asia/Shanghai]​​​ 表示使用的是以​​上海​​为基准的时间。

4. Cookie 路由谓词

Cookie路由谓词工厂采用的是两个参数,一个是Cookie的名字,另外一个是合法的正则表达式。这个谓词用于匹配具有给定名称的Cookie,并且值匹配一个合法的正则表达式。

spring:
cloud:
gateway:
routes:
- id: gateway-service
uri: http://www.163.com
predicates:
- Cookie= username,kee.e

说明:这里是采用验证cookie的方式,当我们请求中携带了对应的正确的cookie信息,就可以访问成功到​​http://www.163.com​​​ , 否则就会报 ​​Not Found​​ .

下面是使用Postman测试的结果:

错误的cookie信息:

Gateway的路由谓词工厂_User_02

正确的cookie信息:

Gateway的路由谓词工厂_SpringCloud Alibaba_03

如果使用gateway时, 需要取出 cookie信息,可以使用下面的方法:

@GetMapping("/resp")
public String test(@CookieValue("username") String username) {
return "SUCCESS";
}

5. Header 路由谓词

Header 路由谓词工厂接受两个参数:header的name和其对应的合法的正则表达式值。只有在Header部分存在name并且其value也匹配的情况下,才能通过。

spring:
cloud:
gateway:
routes:
- id: gateway-service
uri: http://www.163.com
predicates:
- Header=password,123456

测试结果如下:

Gateway的路由谓词工厂_SpringCloud Alibaba_04

如果使用Gateway,需要从Header中取出信息,可以使用下面的方法:

@GetMapping(value = "/testHeader")
public String testHeader(@RequestHeader(value = "username") String username){
return "username:"+username;
}

6. Host 路由谓词

Host(主机)路由谓词工厂,采用一个参数:主机名模式列表。该模式带有​​.​​​ 作为分隔符的Ant样式的模式,谓词与​​Host​​ 匹配模式的Header部分。

spring:
cloud:
gateway:
routes:
- id: gateway-service
uri: http://localhost:8888
predicates:
- Host= localhost:9999

这里为了更好的测试,我们单创建并启动一个服务,端口为8888的,大概代码如下:

/**
* @author hao.ouYang
* @create 2019-10-25 18:08
*/
@RestController
public class UserController {
@Autowired
private UserService userService;

@RequestMapping("/user")
public User findUser(){
return userService.findUser();
}
}

@Service
public class UserService {
public User findUser(){
User user = new User(1,"admin","admin");
return user;
}
}

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User implements Serializable {
private Integer id;
private String username;
private String password;
}

测试结果如下:

Gateway的路由谓词工厂_spring_05

上面其实是将​​http://localhost:9999/user​​​ 映射到了 ​​http://localhost:8888/user​​ 上了。

注意:当然除了我们除了上面的写法,还有一些多样化的定制。同时也支持URI模板变量

- Host= www.ouyang.**, **.ouyang.**,**.ouyang.org
# 上面的例子可以匹配 www.ouyang.club, www.ouyang.com, www.ouyangorg等。
- Host= {sub}.ouyang.club

7. Method 路由谓词

方法路由谓词工厂采用一个参数:用来匹配HTTP请求的类型。(GET,POST等).

spring:
cloud:
gateway:
routes:
- id: gateway-service
uri: http://localhost:8888
predicates:
- Method= POST

以上需要匹配为​​POST​​​ 类型的请求才可以转发到 ​​http://localhost:8888​​ 上面,测试如下:

Gateway的路由谓词工厂_SpringCloud Alibaba_06

更改为​​POST​​ 类型的请求:

Gateway的路由谓词工厂_User_07

8. Path 路由谓词

​PathRoutePredicateFactory​​​ 需要​​PathMatcher​​​ 模式路径列表和一个可选的标志位参数​​matchOptionalTrailingSeparator​​. 这是最常用的一个路由谓词。

spring:
cloud:
gateway:
routes:
- id: gateway-service
uri: http://localhost:8888
predicates:
- Path= /path

这种使用路径来映射的方式。以上可以将​​http://localhost:9999/path​​​ 映射到​​http://localhost:8888/path​​​ 路径上,前一节也见过这个谓词,所以说这个谓词是最常用。还可以通过下面这个方式在请求路径上携带参数:(如果通过这种形式配置,在匹配命中进行路由的同时,会提取路径中对应的内容并且将键值对放在​​ServerWebExchange.getAttributes()​​​集合中,Key为​​ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE​​​, 这些提取出来的属性可以供​​GatewayFilter Factories​​ 使用)。

spring:
cloud:
gateway:
routes:
- id: gateway-service
uri: http://localhost:8888
predicates:
- Path= /testPath/{stri}

另一个服务的接收:

@GetMapping(value = "/path")
public String path(){
return "path";
}

@GetMapping(value = "/testPath/{str}")
public String testPath(@PathVariable("str") String str){
return "return:"+str;
}

9. Query 路由谓词

请求查询参数路由工厂​​QueryRoutePredicateFactory​​ 需要一个必须的请求查询参数(Param的name)以及一个可选的正则表达式(regexp).

spring:
application:
name: spring-cloud-gateway
cloud:
gateway:
routes:
- id: gateway-service
uri: http://localhost:8888
predicates:
- Query= username

通过上述配置,我们的请求中只需要包含​​username​​参数即可匹配路由。

curl localhost:9999/testQuery?username=1

上面的测试可以通过,但是如果把​​username​​ 删除或是改成别的,就无法匹配了。

还可以将Query参数以键值对的形式来配置,这样的请求过来的时候,不仅需要匹配名字,同时参数值需要与正则表达式匹配才能走路径。

spring:
application:
name: spring-cloud-gateway
cloud:
gateway:
routes:
- id: gateway-service
uri: http://localhost:8888
predicates:
- Query= username,ad.

以上匹配需要请求满足既有​​username​​​ 参数,并且值需要以​​ad​​ 开头的长度为3的字符串才能匹配和路由。

测试如下:

curl http://localhost:9999/testQuery?username=adv
{"param":"adv"}

curl http://localhost:9999/testQuery?username=addv
{"timestamp":"2019-10-27T09:15:45.580+0000","path":"/testQuery","status":404,"error":"Not Found","message":null}

8888端口服务的controller方法为:

@GetMapping(value = "/testQuery")
public Map<String,String> testQuery(@RequestParam("username") String username){
Map<String,String> map = new HashMap<>();
map.put("param",username);
return map;
}

10. RemoteAddr 路由谓词

​RemoteAddrRoutePredicateFactory​​匹配规则采用CIDR符号(IPv4或IPv6)字符串的列表(最小值为1),例如192.168.0.1/16(其中192.168.0.1是远程IP地址并且16是子网掩码)。

spring:
application:
name: spring-cloud-gateway
cloud:
gateway:
routes:
- id: gateway-service
uri: http://localhost:8888
predicates:
- RemoteAddr= 127.0.0.1
server:
port: 9999

8888端口服务的处理方法:

@GetMapping(value = "/remote")
public String testRemote(){
return "Remote";
}

测试结果:

curl http://127.0.0.1:9999/remote
# 响应结果
Remote

11. Weight 路由谓词

权重路由谓词工厂采用两个参数,分别为组(group)和权重(weight). 权重按组进行计算。

spring:
application:
name: spring-cloud-gateway
cloud:
gateway:
routes:
- id: gateway-weight-high
uri: http://localhost:8888
predicates:
- Weight= Group1, 8
- id: gateway-weight-low
uri: http://localhost:7777
predicates:
- Weight= Group1, 2
server:
port: 9999

接受7777和8888请求的方法:

//============port:7777 ============
@GetMapping(value = "/weight")
public Map weight() {
Map<String, Object> map = new HashMap<>();
map.put("port", "7777");
return map;
}

//============port:8888 ============
@GetMapping(value = "/weight")
public Map weight() {
Map<String, Object> map = new HashMap<>();
map.put("port", "8888");
System.out.println(map);
return map;
}

测试结果如下:

Gateway的路由谓词工厂_User_08

举报

相关推荐

0 条评论