SpringCloud Gateway中Route Predicate Factories详细说明

官网地址:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#gateway-request-predicates-factories

在这里插入图片描述

Spring Cloud Gateway将路由匹配作为Spring WebFlux HandlerMapping基础架构的一部分。

Spring Cloud Gateway 包含许多内置的Route Predicate Factories。所有这些Predicate 都匹配HTTP请求的不同属性。多种Predicate 工厂可以通过逻辑and进行组合。

Spring Cloud Gateway 创建 Route 对象时, 使用 RoutePredicateFactory 创建 Predicate 对象,Predicate 对象可以赋值给 Route。

如上图所示,gateway默认提供了11中路由断言工厂供用户组合使用。项目启动时会默认加载这些工厂:

在这里插入图片描述

【1】 After Route Predicate Factory

匹配发生在指定日期的请求。

The after route predicate factory takes one parameter, a datetime. This predicate matches requests that happen after the specified datetime.

- id: payment_routh2 # 路由id,没有
   uri:  lb://cloud-payment-service
   predicates:
     - After=2024-02-05T15:10:03.685+08:00[Asia/Shanghai]         # 断言,路径相匹配的进行路由

其中After后的时间串可以如下得到:

public class ZonedDateTimeDemo
{
    public static void main(String[] args)
    {
        ZonedDateTime zbj = ZonedDateTime.now(); // 默认时区
        System.out.println(zbj);
//        ZonedDateTime zny = ZonedDateTime.now(ZoneId.of("America/New_York")); // 用指定时区获取当前时间
//        System.out.println(zny);
    }
}

【2】Before Route Predicate Factory

匹配发生在指定日期时间 的请求。

- id: payment_routh2 # 路由id,没有
   uri:  lb://cloud-payment-service
   predicates:
     - Before=2024-02-05T15:10:03.685+08:00[Asia/Shanghai]         # 断言,路径相匹配的进行路由

【3】Between Route Predicate Factory

匹配发生在两个指定日期时间 中间的请求。

- id: payment_routh2 # 路由id,没有
   uri:  lb://cloud-payment-service
   predicates:
     - Between=2024-02-05T15:10:03.685+08:00[Asia/Shanghai],2024-02-25T15:10:03.685+08:00[Asia/Shanghai]        
      # 断言,路径相匹配的进行路由

【4】Cookie Route Predicate Factory

Cookie Route Predicate需要两个参数,一个是 Cookie name ,一个是正则表达式。

路由规则会通过获取对应的 Cookie name 值和正则表达式去匹配,如果匹配上就会执行路由,如果没有匹配上则不执行

spring:
  cloud:
    gateway:
      routes:
      - id: cookie_route
        uri: https://example.org
        predicates:
        - Cookie=chocolate, ch.p

【5】Header Route Predicate Factory

请求头匹配,需要两个参数:请求头名称和正则表达式。如果请求头属性值和正则表达式匹配,则执行路由。

spring:
  cloud:
    gateway:
      routes:
      - id: header_route
        uri: https://example.org
        predicates:
        - Header=X-Request-Id, \d+

【6】Host Route Predicate Factory

主机地址匹配,只有一个参数:一组主机列表,其是Ant风格,以.为分隔符。如果请求头中的Host匹配主机列表,则执行路由。

spring:
  cloud:
    gateway:
      routes:
      - id: host_route
        uri: https://example.org
        predicates:
        - Host=**.somehost.org,**.anotherhost.org

参数值同样支持URI 模板变量,比如{sub}.myhost.org。如果一个请求有请求头Host且值比如www.somehost.org或beta.somehost.org或www.anotherhost.org均会执行路由。

【7】Method Route Predicate Factory

请求方法匹配,参数值为一个或多个请求方法。

spring:
  cloud:
    gateway:
      routes:
      - id: method_route
        uri: https://example.org
        predicates:
        - Method=GET,POST

【8】Path Route Predicate Factory

路径匹配,支持通配符和URI template variables。

spring:
  cloud:
    gateway:
      routes:
      - id: host_route
        uri: https://example.org
        predicates:
        - Path=/red/{segment},/blue/{segment}

{segment},其实就是ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE得到的map中,map.get("segment")对应的值。

匹配所有请求:

- Path=/**    

【9】Query Route Predicate Factory

查询参数匹配,两个参数:参数名和值正则表达式(可选)。

  • 如果只有一个参数,参数名,则表示查询参数必须包含该参数
  • 如果有两个参数,则表示参数值还要符合正则表达式

一个参数实例:

spring:
  cloud:
    gateway:
      routes:
      - id: query_route
        uri: https://example.org
        predicates:
        - Query=green

两个参数实例:

spring:
  cloud:
    gateway:
      routes:
      - id: query_route
        uri: https://example.org
        predicates:
        - Query=red, gree.

【10】The RemoteAddr Route Predicate Factory

请求目标地址匹配,只有一个参数:为一组IPV4或IPV6的地址,比如192.168.0.1/16。

spring:
  cloud:
    gateway:
      routes:
      - id: remoteaddr_route
        uri: https://example.org
        predicates:
        - RemoteAddr=192.168.1.1/24

在这里插入图片描述

【11】Weight Route Predicate Factory

The weight route predicate factory takes two arguments: group and weight. The weights are calculated per group.

spring:
  cloud:
    gateway:
      routes:
      - id: weight_high
        uri: https://weighthigh.org
        predicates:
        - Weight=group1, 8
      - id: weight_low
        uri: https://weightlow.org
        predicates:
        - Weight=group1, 2

This route would forward ~80% of traffic to weighthigh.org and ~20% of traffic to weighlow.org

【12】自定义路由断言

这里我们可以参考AfterRoutePredicateFactory 来自定义路由断言。

public class AfterRoutePredicateFactory extends AbstractRoutePredicateFactory<AfterRoutePredicateFactory.Config> {

	/**
	 * DateTime key.
	 */
	public static final String DATETIME_KEY = "datetime";

	public AfterRoutePredicateFactory() {
		super(Config.class);
	}

	@Override
	public List<String> shortcutFieldOrder() {
		return Collections.singletonList(DATETIME_KEY);
	}

	@Override
	public Predicate<ServerWebExchange> apply(Config config) {
		return new GatewayPredicate() {
			@Override
			public boolean test(ServerWebExchange serverWebExchange) {
				final ZonedDateTime now = ZonedDateTime.now();
				return now.isAfter(config.getDatetime());
			}

			@Override
			public Object getConfig() {
				return config;
			}

			@Override
			public String toString() {
				return String.format("After: %s", config.getDatetime());
			}
		};
	}

	public static class Config {

		@NotNull
		private ZonedDateTime datetime;

		public ZonedDateTime getDatetime() {
			return datetime;
		}

		public void setDatetime(ZonedDateTime datetime) {
			this.datetime = datetime;
		}

	}

}

总结如下:

  • 要么继承AbstractRoutePredicateFactory抽象类
  • 要么实现RoutePredicateFactory接口
  • 开头任意取名,但是必须以RoutePredicateFactory后缀结尾

① 新建MyRoutePredicateFactory继承AbstractRoutePredicateFactory类

@Component
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config>
{   
}

② 重写apply方法

假设需要请求传递参数userType,且值满足某种规则。

@Component
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config>
{


    @Override
    public Predicate<ServerWebExchange> apply(MyRoutePredicateFactory.Config config)
    {
        return new Predicate<ServerWebExchange>()
        {
            @Override
            public boolean test(ServerWebExchange serverWebExchange)
            {
                //检查request的参数里面,userType是否为指定的值,符合配置就通过
                //http://localhost:9527/pay/gateway/get/1?userType=diamond
                String userType = serverWebExchange.getRequest().getQueryParams().getFirst("userType");
                if (userType == null) {
                    return false;
                }
                //如果说参数存在,就和config的数据进行比较
                if(userType.equalsIgnoreCase(config.getUserType())){
                    return true;
                }
                return false;
            }
        };
    }
}

③ 新建apply方法所需要的静态内部类MyRoutePredicateFactory.Config

@Component
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config>
{

//空参构造方法,内部调用super
    public MyRoutePredicateFactory()
    {
        super(MyRoutePredicateFactory.Config.class);
    }

    //这个Config类就是我们的路由断言规则,重要
    @Validated
    public static class Config
    {
        @Setter
        @Getter
        @NotEmpty
        private String userType; //钻/金/银和yml配置的会员等级
    }


    @Override
    public Predicate<ServerWebExchange> apply(MyRoutePredicateFactory.Config config)
    {
        return new Predicate<ServerWebExchange>()
        {
            @Override
            public boolean test(ServerWebExchange serverWebExchange)
            {
                //检查request的参数里面,userType是否为指定的值,符合配置就通过
                //http://localhost:9527/pay/gateway/get/1?userType=diamond
                String userType = serverWebExchange.getRequest().getQueryParams().getFirst("userType");
                if (userType == null) {
                    return false;
                }
                //如果说参数存在,就和config的数据进行比较
                if(userType.equalsIgnoreCase(config.getUserType())){
                    return true;
                }
                return false;
            }
        };
    }
}

④ 支持短路配置

重写shortcutFieldOrder方法:

@Component
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config>
{

    public MyRoutePredicateFactory()
    {
        super(MyRoutePredicateFactory.Config.class);
    }

    //这个Config类就是我们的路由断言规则,重要
    @Validated
    public static class Config
    {
        @Setter
        @Getter
        @NotEmpty
        private String userType; //钻/金/银和yml配置的会员等级
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Collections.singletonList("userType");
    }

    @Override
    public Predicate<ServerWebExchange> apply(MyRoutePredicateFactory.Config config)
    {
        return new Predicate<ServerWebExchange>()
        {
            @Override
            public boolean test(ServerWebExchange serverWebExchange)
            {
                //检查request的参数里面,userType是否为指定的值,符合配置就通过
                //http://localhost:9527/pay/gateway/get/1?userType=diamond
                String userType = serverWebExchange.getRequest().getQueryParams().getFirst("userType");
                if (userType == null) {
                    return false;
                }
                //如果说参数存在,就和config的数据进行比较
                if(userType.equalsIgnoreCase(config.getUserType())){
                    return true;
                }
                return false;
            }
        };
    }
}

Fully Expanded Arguments

- name: My
  args:
    userType: diamond

Shortcut Configuration:

- My=diamond

浏览器请求测试:http://localhost:9527/pay/gateway/get/1?userType=diamond

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流烟默

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值