Gateway Predicate断言(谓词)

是什么

Spring Cloud Gateway匹配路由作为Spring WebFlux HandlerMapping基础设施的一部分。 Spring Cloud Gateway包含许多内置的路由谓词工厂。 所有这些谓词都匹配HTTP请求的不同属性。 您可以使用逻辑 and 语句来联合收割机组合多个路由谓词工厂。

Predicate就是为了实现一组匹配规则,让请求过来找到对应的Route进行处理。

分类

idea启动项目打印的日志:

常用的内置Route Predicate

id:我们自定义的路由 ID,保持唯一

uri:目标服务地址

predicates:路由条件,Predicate接受一个输入参数返回一个布尔值。

该属性包含多种默认方法来将Predicate组合成其他复杂的逻辑(比如:与,或,非)

配置语法总体概述

2种配置方式,二选一

短格式配置

完全展开配置

测试地址

http://localhost:9527/pay/gateway/get/1

After Route Predicate

After路由谓词工厂接受一个datetime参数(这是一个java ZonedDateTime)。

在指定日期时间之后才可以请求该地址。

bash 复制代码
spring:
  cloud:
    gateway:
      routes:
        - id: after_route
          uri: lb://cloud-payment-service
          predicates:
            - Path=/pay/gateway/get/**
            - After=2024-04-24T23:56:23.970133500+08:00[Asia/Shanghai]

如何获取ZonedDateTime

java 复制代码
import java.time.ZonedDateTime;

public class Testtt {
    public static void main(String[] args) {
        ZonedDateTime zonedDateTime = ZonedDateTime.now().plusMinutes(1);   // 1分钟之后的时间
        System.out.println(zonedDateTime);
    }
}

Before Route Predicate

Before路由谓词工厂接受一个datetime参数(这是一个java ZonedDateTime)。

在指定日期时间之前才可以请求该地址。

bash 复制代码
spring:
  cloud:
    gateway:
      routes:
        - id: before_route
          uri: lb://cloud-payment-service
          predicates:
            - Path=/pay/gateway/get/**
            - Before=2024-04-25T00:02:10.783066100+08:00[Asia/Shanghai]

Between Route Predicate

Between路由谓词工厂接受两个参数,datetime1和datetime2(都是Java ZonedDateTime)。用英文逗号分隔。

在datetime1之后和datetime2之前可以请求该地址。

datetime2参数必须在datetime1之后。

bash 复制代码
spring:
  cloud:
    gateway:
      routes:
        - id: between_route
          uri: lb://cloud-payment-service
          predicates:
            - Path=/pay/gateway/get/**
            - Between=2024-04-24T23:56:23.970133500+08:00[Asia/Shanghai], 2024-04-25T00:02:10.783066100+08:00[Asia/Shanghai]

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

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

java 复制代码
spring:
  cloud:
    gateway:
      routes:
        - id: cookie_route
          uri: lb://cloud-payment-service
          predicates:
            - Path=/pay/gateway/get/**
            - Cookie=chocolate, ch.p

Header Route Predicate

Header路由谓词工厂接受两个参数,header和regexp(这是一个Java正则表达式)。

此谓词与具有给定名称且其值与正则表达式匹配的标头匹配。

java 复制代码
spring:
  cloud:
        service-name: ${spring.application.name}
    gateway:
      routes:
        - id: header_route
          uri: lb://cloud-payment-service
          predicates:
            - Path=/pay/gateway/get/**
            - Header=X-Request-Id, [0-9]+

Host Route Predicate

Host Route Predicate 接收一组参数,一组匹配的域名列表,这个模板是一个 ant 分隔的模板,用.号作为分隔符。

它通过参数中的主机地址作为匹配规则。

spring:
  cloud:
    gateway:
      routes:
        - id: pay_routh1
          uri: lb://cloud-payment-service
          predicates:
            - Path=/pay/gateway/get/**
            - Host=**.somehost.org,**.anotherhost.org

Path Route Predicate

路径相匹配的进行路由

spring:
  cloud:
    gateway:
      routes:
        - id: pay_routh1
          uri: lb://cloud-payment-service
          predicates:
            - Path=/pay/gateway/get/**

Query Route Predica

Query路由谓词工厂有两个参数:一个必需的param和一个可选的regexp(这是一个Java正则表达式)。

请求包含param查询参数。

spring:
  cloud:
    gateway:
      routes:
        - id: pay_routh1
          uri: lb://cloud-payment-service
          predicates:
            - Path=/pay/gateway/get/**
            - Query=green

RemoteAddr route predicate

RemoteAddr路由断言工厂采用sources的列表(最小大小为1),这些列表是CIDR表示法(IPv4或IPv6)字符串,例如192.168.0.1/16(其中192.168.0.1是IP地址,16是子网掩码)。

什么是计算机网络中的 CIDR

spring:
  cloud:
    gateway:
      routes:
        - id: pay_routh1
          uri: lb://cloud-payment-service
          predicates:
            - Path=/pay/gateway/get/**
            - RemoteAddr=192.168.31.171/24

Method Route Predicat

Method路由谓词工厂接受一个methods参数,它是一个或多个参数:要匹配的HTTP方法。

配置某个请求地址,只能用Get/Post方法访问,方法限制。

spring:
  cloud:
    gateway:
      routes:
        - id: pay_routh1
          uri: lb://cloud-payment-service
          predicates:
            - Path=/pay/gateway/get/**
            - Method=GET,POST

Weight Route Predicat

Weight路由谓词工厂有两个参数:group和weight(一个int)。计算每组的权重。

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

该路由将把80%的流量转发到weightthigh.org,20%的流量转发到weightlow.org

自定义断言

规则:

要么继承AbstractRoutePredicateFactory抽象类

要么实现RoutePredicateFactory接口

开头任意取名,但是必须以RoutePredicateFactory后缀结尾

仿照:AfterRoutePredicateFactory

自定义XXXRoutePredicateFactory

  1. 新建类名XXX需要以RoutePredicateFactory结尾,并继承AbstractRoutePredicateFactory类。

  2. 重写apply方法

  3. 新建apply方法所需要的静态内部类MyRoutePredicateFactory.Config,这个Config类就是我们的路由断言规则,重要

  4. 空参构造方法,内部调用super

  5. 重载 shortcutFieldOrder 方法

不重载,配置的时候只能完全展开配置,不能短格式配置。

java 复制代码
package com.yq.springcloud.predicate;

import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;

import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;

public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config> {

    public static final String PARAM_USERTYPE = "userType";

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

    /**
     * 返回有关参数数和快捷方式分析顺序的提示
     * @return
     */
    @Override
    public List<String> shortcutFieldOrder() {
        return Collections.singletonList(PARAM_USERTYPE);
    }

    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        return serverWebExchange -> {
            //检查request的参数里面,userType是否为指定的值,符合配置就通过
            String userType = serverWebExchange.getRequest().getQueryParams().getFirst(PARAM_USERTYPE);

            if (userType == null) return false;

            //如果说参数存在,就和config的数据进行比较
            if (userType.equals(config.getUserType())) {
                return true;
            }
            return false;
        };
    }

    @Validated
    @Data
    public static class Config {
        @NotBlank
        private String userType; //钻、金、银等用户等级
    }
}

自定义GatewayAutoConfiguration

仿照:org.springframework.cloud.gateway.config.GatewayAutoConfiguration

将自己自定义的断言加入IOC

java 复制代码
package com.yq.springcloud.config;

import com.yq.springcloud.predicate.MyRoutePredicateFactory;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration;
import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.gateway.config.GatewayClassPathWarningAutoConfiguration;
import org.springframework.cloud.gateway.config.GatewayReactiveLoadBalancerClientAutoConfiguration;
import org.springframework.cloud.gateway.config.conditional.ConditionalOnEnabledPredicate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMissing = true)
@EnableConfigurationProperties
@AutoConfigureBefore({ HttpHandlerAutoConfiguration.class, WebFluxAutoConfiguration.class })
@AutoConfigureAfter({ GatewayReactiveLoadBalancerClientAutoConfiguration.class,
        GatewayClassPathWarningAutoConfiguration.class })
public class MyGatewayAutoConfiguration {

    @Bean
    @ConditionalOnEnabledPredicate
    public MyRoutePredicateFactory myRoutePredicateFactory() {
        return new MyRoutePredicateFactory();
    }
}

配置文件中添加配置断言

java 复制代码
spring:
  cloud:
    gateway:
      routes:
        - id: pay_routh1
          uri: lb://cloud-payment-service
          predicates:
            - Path=/pay/gateway/get/**
            - My=diamond

测试

1, 启动的时候,已加载到断言中

  1. 只有userType=diamond才可以正常访问。
相关推荐
炸裂狸花猫1 天前
Kubernetes从零到精通(12-Ingress、Gateway API)
容器·kubernetes·gateway
云来喜3 天前
关于Spring Cloud Gateway中 Filters的理解
java·spring boot·gateway
小小小小关同学3 天前
【Gateway】网关服务快速上手
java·开发语言·gateway
小小小小关同学3 天前
【Gateway】Gateway Filter Factories
网络·gateway
两仪式quq3 天前
服务网关Gateway快速入门
服务器·网络·gateway
szc17675 天前
Gateway学习笔记
笔记·学习·gateway
huaqianzkh8 天前
什么是API网关(API Gateway)?
架构·gateway
亚林瓜子8 天前
Spring Cloud Gateway中的常见配置
spring·spring cloud·gateway
c1tenj28 天前
SpringCloud gateway
gateway
潘多编程8 天前
Gateway Timeout504: 网关超时的完美解决方法
gateway