Spring Cloud Gateway自定义断言

问题:Spring Cloud Gateway自带的断言(Predicate)不满足业务怎么办?可以自定义断言!

先看Spring Cloud Gateway是如何实现断言的

Gateway中断言的整体架构如下:

public abstract class AbstractRoutePredicateFactory<C> extends AbstractConfigurable<C>
		implements RoutePredicateFactory<C> {

	public AbstractRoutePredicateFactory(Class<C> configClass) {
		super(configClass);
	}
}

可以看到Gateway的断言都是继承了AbstractRoutePredicateFactory抽象类。

自定义路由断言规则的步骤如下:

  1. 新建类名CustomRoutePredicateFactory(类名需要以以RoutePredicateFactory结尾),并继承AbstractRoutePredicateFactory抽象类。
  2. 重写apply()方法
  3. 新建apply()方法所需的静态内部类CustomRoutePredicateFactory.Config,这个Config就是我们的断言规则
  4. 空参构造方法,内部调用super()方法
  5. 在Config类中配置自定义参数
  6. apply()中编写自定义的逻辑
import jakarta.validation.constraints.NotNull;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.GatewayPredicate;
import org.springframework.web.server.ServerWebExchange;

import java.util.function.Predicate;

/**
 * 自定义路由断言工厂,指定的用户类型才能访问
 *
 * @author gengduc@qq.com
 * @since 2024-03-08
 */
@Component
public class CustomRoutePredicateFactory extends AbstractRoutePredicateFactory<CustomRoutePredicateFactory.Config> {
    public CustomRoutePredicateFactory() {
        super(CustomRoutePredicateFactory.Config.class);
    }

    @Override
    public Predicate<ServerWebExchange> apply(CustomRoutePredicateFactory.Config config) {
        return new GatewayPredicate() {
            @Override
            public boolean test(ServerWebExchange serverWebExchange) {
                // 这里可以编写自定义的逻辑
                // 获取请求中的信息,判断是否符合条件
                String userType = serverWebExchange.getRequest().getQueryParams().getFirst("userType");
                if (userType == null) {
                    return false;
                }
                // 判断用户类型是否符合
                return userType.equalsIgnoreCase(config.getUserType());
            }
        };
    }

    public static class Config {
        // 这里可以配置一些参数
        @NotNull
        private String userType;

        public String getUserType() {
            return userType;
        }

        public void setUserType(String userType) {
            this.userType = userType;
        }
    }
}

这个时候已经可以使用我们自定义的断言了。

http://localhost:9527/order/gateway/get/1?userType=admin

在yml文件中配置:

spring:
  cloud:
    gateway:
      routes:
      - id: custom_route
        uri: https://example.org
        predicates:
        - name: Custom
          args:
            userType: admin # 当用户类型是admin的时候进行路由转发

可以看到我们使用的配置方式是完全展开的参数配置方式(Fully Expanded Arguments),这个时候还是不支持快捷配置的。

为了让自定义的断言支持快捷配置(Shortcut Configuration),还需要实现shortcutFieldOrder()方法。

image-20240308195902106

完整的代码如下:

import jakarta.validation.constraints.NotNull;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.GatewayPredicate;
import org.springframework.web.server.ServerWebExchange;

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

/**
 * 自定义路由断言工厂,指定的用户类型才能访问
 *
 * @author gengduc@qq.com
 * @since 2024-03-08
 */
@Component
public class CustomRoutePredicateFactory extends AbstractRoutePredicateFactory<CustomRoutePredicateFactory.Config> {
    public CustomRoutePredicateFactory() {
        super(CustomRoutePredicateFactory.Config.class);
    }
	
    // 快捷配置支持
    @Override
    public List<String> shortcutFieldOrder() {
        return Collections.singletonList("userType");
    }

    @Override
    public Predicate<ServerWebExchange> apply(CustomRoutePredicateFactory.Config config) {
        return new GatewayPredicate() {
            @Override
            public boolean test(ServerWebExchange serverWebExchange) {
                // 这里可以编写自定义的逻辑
                // 获取请求中的信息,判断是否符合条件
                String userType = serverWebExchange.getRequest().getQueryParams().getFirst("userType");
                if (userType == null) {
                    return false;
                }
                // 判断用户类型是否符合
                return userType.equalsIgnoreCase(config.getUserType());
            }
        };
    }



    public static class Config {
        // 这里可以配置一些参数
        @NotNull
        private String userType;

        public String getUserType() {
            return userType;
        }

        public void setUserType(String userType) {
            this.userType = userType;
        }
    }
}

相关推荐

  1. SpringCloudGateway

    2024-03-12 01:54:01       26 阅读
  2. 定义中间件

    2024-03-12 01:54:01       48 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-12 01:54:01       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-12 01:54:01       106 阅读
  3. 在Django里面运行非项目文件

    2024-03-12 01:54:01       87 阅读
  4. Python语言-面向对象

    2024-03-12 01:54:01       96 阅读

热门阅读

  1. 如何远程SSH连接在家的服务器主机

    2024-03-12 01:54:01       45 阅读
  2. SpringBoot项目中同时支持https和http协议

    2024-03-12 01:54:01       39 阅读
  3. 英语听力 3.11

    2024-03-12 01:54:01       41 阅读
  4. vue使用西瓜视频插件xgplayer

    2024-03-12 01:54:01       99 阅读
  5. Leetcode 189. 轮转数组

    2024-03-12 01:54:01       44 阅读
  6. C++split的替代方法

    2024-03-12 01:54:01       46 阅读
  7. Go语言中,如何调用C++的dll文件

    2024-03-12 01:54:01       48 阅读
  8. Python中输入输出函数input和print用法

    2024-03-12 01:54:01       39 阅读