加入收藏 | 设为首页 | 会员中心 | 我要投稿 武陵站长网 (https://www.50888.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

PHP过滤器 spring-cloud

发布时间:2023-01-30 16:31:05 所属栏目:PHP教程 来源:网络
导读: 1. 上回书传送门:2. 概述
在上一篇,我们分析了spring-cloud-gateway请求路由过程的前两步:

我们知道第二步拿到的Handler,实际上是第一步匹配到的RoutePredicateHandlerMapping所持有的

1. 上回书传送门:2. 概述

在上一篇,我们分析了spring-cloud-gateway请求路由过程的前两步:

PHP过滤器_php 过滤 敏感词_过滤式自救器过滤什么气体

我们知道第二步拿到的Handler,实际上是第一步匹配到的RoutePredicateHandlerMapping所持有的FilteringWebHandler对象。而它的本职工作是将GlobalFilter(全局过滤器)、GatewayFilter(一般来说是我们自己配置的,当然也默认内置了一些),放到同一个List里进行优先级排序PHP过滤器,生成一个过滤器链。执行过滤器链,就能顺序执行链中保存的所有Filter。

3. 源码分析3.1 初始化时加载所有全局过滤器

public class FilteringWebHandler implements WebHandler {
    // 所有全局过滤器
    private final List<GatewayFilter> globalFilters;
    public FilteringWebHandler(List<GlobalFilter> globalFilters) {
        // 1.初始化时加载所有全局过滤器,将他们适配为GatewayFilter类型,方便等会做合并
        this.globalFilters = loadFilters(globalFilters);
    }
    // 适配器模式,通过两次套娃把GlobalFilter封装成GatewayFilter类型
    private static List<GatewayFilter> loadFilters(List<GlobalFilter> filters) {
	return filters.stream().map(filter -> {
            // 2.Adapter持有GlobalFilter的引用
	    GatewayFilterAdapter gatewayFilter = new GatewayFilterAdapter(filter);
	    if (filter instanceof Ordered) {
		int order = ((Ordered) filter).getOrder();
                // 3.OrderedGatewayFilter再持有一个Adapter
                // 其实这里搞的挺无语的,那我直接返回Adapter又不是不能用,毕竟接口相同
                // 说白了,还是跟职责隔离、设计解耦有关
                // 就好比有时我们会纠结干嘛不直接把路由配置读成Route是类似的
                // 因为我们的思维模式,就是快点达到目的,而忽略了扩展性
                // 假设现在我们需要有一个服务提供多个接口,包括了Filter接口的功能
                // 那么,我们还是直接在Adapter上加接口,再持有一个跟它功能无关的工具人干活?
                // 那职责就完全乱套了,我们大可以这样:
                // Kunkun implements ISing,IJump,IRap,IBasketball {
                //     private ISing singAdapter;
                //     private IJump jumpAdapter;
                //     private IRap rapAdapter;
                //     private IBasketball basketballAdapter;
                // }
                // 那么坤坤就会唱、跳、rap、篮球了
		return new OrderedGatewayFilter(gatewayFilter, order);
	    }
	    return gatewayFilter;
        }).collect(Collectors.toList());
}

GatewayFilterAdapter源码片段:

/**
 * GatewayFilter的适配器模式,将filter()操作委托给持有的GlobalFilter实例去执行
 * 这样就可以把GlobalFilter伪装成GatewayFilter来用
 */
private static class GatewayFilterAdapter implements GatewayFilter {

    // 真正干活的
    private final GlobalFilter delegate;
}

OrderedGatewayFilter代码片段:

public class OrderedGatewayFilter implements GatewayFilter, Ordered {
    // 这里实际就是塞的GatewayFilterAdapter,老套娃了
    private final GatewayFilter delegate;
}

3.2 合并GlobalFilter和GatewayFilter

public Mono<Void> handle(ServerWebExchange exchange) {
    // 1.从exchange里拿到第二步匹配好的Route(匹配到后塞进去的)
    Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
    // 2.通过这个Route拿到它对应的GatewayFilter列表
    List<GatewayFilter> gatewayFilters = route.getFilters();
    // 3.把前面已经适配为GatewayFilter的全局过滤器拿过来,初始化一个总的过滤器列表
    List<GatewayFilter> combined = new ArrayList<>(this.globalFilters);
    // 4.然后把从Route里拿到的过滤器列表也塞进去合并
    combined.addAll(gatewayFilters);
    // 5.对总的过滤器列表按优先级排序
    AnnotationAwareOrderComparator.sort(combined);
    // 6.通过这个总的过滤器列表构造一个过滤器链来执行过滤逻辑
    return new DefaultGatewayFilterChain(combined).filter(exchange);
}

3.3 生成过滤器链DefaultGatewayFilterChain

/**
 * 默认的过滤器链实现,其实把叫DefaultGatewayFilterChainElement会更好理解一些。
 * 假设我们把一个DefaultGatewayFilterChain的实例称为 chainElement,那么整个
 * 过滤器链实际上是 chainElement -> chainElement -> chainElement的逻辑结构
 */
private static class DefaultGatewayFilterChain implements GatewayFilterChain {
    // 记录当前这个Chain实例对应要执行的filter位置
    private final int index;
    // 所有要执行的filter列表
    private final List<GatewayFilter> filters;
    /**
     * 当我们最开始用一组 filter去初始化得到一个 ChainElement
     * 此时 chainElement的index记录了它所对应的filter为第一个(index=0)
     * 那么我们执行 chainElement.filter()实际执行的是filter_0.filter()
     * 它里面又会返回ChainElement.filter()方法的调用,宁看我,那我也看宁。
     * 于是变成这样蛋疼无比的循环:
     * chainElement0.filter()
     * -> new ChainElement() chainElement1;  ChainElement0.filter.filter(chainElement1);
     * -> newChainElement1.filter()
     * -> new ChainElement() chainElement2;  ChainElement1.filter.filter(chainElement2);
     * -> newChainElement2.filter()

     * -> ...
     * 每次执行ChainElement.filter()都会构造新的newChainElement
     * 然后执行自己对应的filter的filter()
     * 最后newChainElement.filter()
     * 就这样不停循环到所有filter都被执行了才停止构造ChainElement,
     * 返回Mono.empty(),实际上把他想成一个void方法的调用就行了
     */
    DefaultGatewayFilterChain(List<GatewayFilter> filters) {
        this.filters = filters;
        this.index = 0;
    }
    // 通过一个parentChain构造一个新Chain
    // 其实在调用处index=parent.index+1,让它指向下一个filter
    private DefaultGatewayFilterChain(DefaultGatewayFilterChain parent, int index) {
        this.filters = parent.getFilters();
        this.index = index;
    }
    public List<GatewayFilter> getFilters() {
        return filters;
    }
    // 每个Chain的执行方法
    @Override
    public Mono<Void> filter(ServerWebExchange exchange) {
        return Mono.defer(() -> {
            // index没超出filters的下标范围,就说明还有filter可以执行
            if (this.index < filters.size()) {
                // 先通过index拿到当前Chain需要执行的filter
                GatewayFilter filter = filters.get(this.index);
                // 然后构造下一个Chain,让它index+1指向下一个filter
                DefaultGatewayFilterChain chain = new DefaultGatewayFilterChain(this,
                    this.index + 1);
                // 最终还是执行的filter自己的过滤方法,然后开始了套娃
                return filter.filter(exchange, chain);
            }
            // index >= filers.size()时,说明所有的filter都执行完了,直接返回Mono.empty()
            else {
                return Mono.empty(); // complete
            }
        });
    }
}

4. 小结

本篇我们分析了FilteringWebHandler创建和执行过滤器链的流程。由于这种责任链模式写法比较少见,可以把DefaultGatewayFilterChain想象成一个个ChainElement来辅助理解,多看多调试,慢慢就搞懂啦~感谢观看~

5. 下回书已更新

(编辑:武陵站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!