Spring Cloud Gateway自定义断言

本文介绍了如何在SpringCloudGateway中扩展内置的断言功能,通过创建自定义的RoutePredicateFactory实现针对特定用户类型的路由转发。步骤包括新建类继承AbstractRoutePredicateFactory,重写apply方法并配置自定义参数。同时,文章还涵盖了如何支持快捷配置以简化设置。

问题: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;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值