Cookie 路由断言工厂需要两个参数,分别是 Cookie name 和 regexp(Java 正则表达式)。语法如下:
Cookie=Cookie名称, Cookie的值
该断言会匹配具有给定 name 并且其值符合 regexp 正则表达式的 cookie。例如:
spring: cloud: gateway: routes: - id: cookie_route uri: https://example.org predicates: - Cookie=chocolate, ch.p
上面的配置,cookie_route 路由会匹配 cookie 名为 chocolate 并且其值符合 ch.p 正则表达式的请求。注意,正则表达式中 “.” 表示任意字符,因此可以匹配 chap、chwp、……等等。
将“Gateway 搭建网关服务”项目的配置文件 bootstrap.yml 内容使用如下配置替换:
server: # 网关端口 port: 9000 spring: application: # 服务名称 name: gateway-demo01 cloud: # nacos nacos: discovery: server-addr: localhost:8848 username: nacos password: nacos group: DEFAULT_GROUP # 网关路由配置 gateway: # 网关路由配置 routes: # 路由id,自定义,只要唯一集合 - id: service-order # 路由的目标地址,lb 就是负载均衡,后面跟服务名 # 需要集成 nacos 等服务注册中心 uri: lb://service-order # 路由断言,也就是判断请求是否符合路由规则的条件 predicates: # Cookie断言:匹配名为 my_cookie,值为 www.hxstrive.com,其中 www 可以为任何 a-zA-Z0-9 多个字符 - Cookie=my_cookie, [a-zA-Z0-9]+\.hxstrive\.com
重启网关服务,使用 Postman 访问订单接口(注意,需要添加一个名为 my_cookit 的 Cookie),如下图:
从上图可知,成功请求接口,这是因为添加了一个名为 my_cookie,值为 www.hxstrive.com 的 Cookie。如果我们不传递该 Cookie,则请求将返回 404,如下图:
下面是 Cookie 路由断言工厂的源码:
package org.springframework.cloud.gateway.handler.predicate; //... public class CookieRoutePredicateFactory extends AbstractRoutePredicateFactory<CookieRoutePredicateFactory.Config> { public static final String NAME_KEY = "name"; public static final String REGEXP_KEY = "regexp"; public CookieRoutePredicateFactory() { super(Config.class); } @Override public List<String> shortcutFieldOrder() { return Arrays.asList(NAME_KEY, REGEXP_KEY); } @Override public Predicate<ServerWebExchange> apply(Config config) { return exchange -> { // 从请求中获取指定名称的所有 cookie List<HttpCookie> cookies = exchange.getRequest().getCookies().get(config.name); // 如果没有 cookie,则返回 false if (cookies == null) { return false; } // 循环判断 cookie,任何一个 cookie 匹配,则返回 true for (HttpCookie cookie : cookies) { if (cookie.getValue().matches(config.regexp)) { return true; } } return false; }; } @Validated public static class Config { // cookie 名称 @NotEmpty private String name; // 匹配值的正则表达式 @NotEmpty private String regexp; // 配置信息 } }