springcloud Gateway-predicate源码笔记

predicate的大致设计思路。

从uml类图看初始接口RoutePredicateFactory。PredicateFactory顾名思义Predicate工厂,这是一个函数式接口,函数式方法就是工厂方法apply(Config config).

Predicate<ServerWebExchange> apply(C config);返回一个Predicate实例。

抽象方法增加了对configConfigurable的抽象类,顾名思义这厮一个可配置配置化支持接口。用于获取我们在yml配置时候注入的配置对象。

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

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

}

下面是AfterRoutePredicateFactory的源码,主要就是实现apply方法,和声明的静态内部类Config类.很显然只需要获取一个配置时间。所以Config的参数也就只有时间。

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) {
		ZonedDateTime datetime = config.getDatetime();
		return exchange -> {
			final ZonedDateTime now = ZonedDateTime.now();
			return now.isAfter(datetime);
		};
	}

	public static class Config {

		@NotNull
		private ZonedDateTime datetime;

		public ZonedDateTime getDatetime() {
			return datetime;
		}

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

	}

}
把apply方法单独拎出来,这是一个lambda的写法,这里声明了一个Predicate<ServerWebExchange>类型的匿名内部类。Predicate也是一个函数式接口,它的函数式方法test,所以lambda表达式{}部分就是test的实现。而exchange就是test的参数。
	@Override
	public Predicate<ServerWebExchange> apply(Config config) {
		ZonedDateTime datetime = config.getDatetime();
		return exchange -> {
			final ZonedDateTime now = ZonedDateTime.now();
			return now.isAfter(datetime);
		};
	}

Predicate接口源代码,一个函数式泛型接口。参数化类型T.也就是上面的ServerWebExchange.


@FunctionalInterface
public interface Predicate<T> {

    boolean test(T t);

    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }

    default Predicate<T> negate() {
        return (t) -> !test(t);
    }

   
    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }

   
    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
}

源码的内部设计流程呢是。从工厂类PredicateFactory开始,在这里定义配置类Config,我们调用工厂方方法aplay(),传递进去不同的配置文件生成一个个Predicate<ServerWebExchange>匿名内部类,同时实现了test方法(声明Predicate的内部类必须实现它的非默认方法)。Predicate实例至此被加载,在被调用的时候传入ServerWebExchange实例。整个流程就是这么回事了。

自定义PredicateFactory,需要注意的就是config定义,config参数注入(shortcutFieldOrder这个方法排序注入)。然后就是根据需求编写test了。


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

    /**
     * Name key.
     */
    public static final String AGE_KEY = "age";

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


    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList(AGE_KEY);
    }

    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        //奶奶的这个exchange是被传进来的
        return exchange -> {
            MultiValueMap<String, String> queryParams = exchange.getRequest().getQueryParams();
            String age = queryParams.getFirst("age");
            if (!StringUtils.isEmpty(age) && age.matches("[0-9]+")) {
                int iAge = Integer.parseInt(age);
                if (iAge < config.getAge()) {
                    return true;
                }
            }
            return false;
        };
    }


    @Validated
    public static class Config {
        @NotNull
        private Integer age;

        public Integer getAge() {
            return age;
        }

        public void setAge(Integer age) {
            this.age = age;
        }
    }

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值