CloudGatewayFilter 是 ExFilter 的扩展接口，主要是为了突出名字的专属性。使用时与 Filter 的区别：

* 最后要返回一个 `Completable`。**用于触发一个响应式订阅，从而让异步结束**。
* 所有的异常，也要用 `Completable.error(err)` 返回

作用范围是网关全局。

### 1、网关全局过滤器

| 接口                               | 说明                                                                                         | 
| -------------------- | ---------------------------------------------------- | 
| CloudGatewayFilter          | 原始网关过滤器接口                                                                    | 
| CloudGatewayFilterMix     | 组合网关过滤器接口，可以方便组合 RoutePredicateFactory               | 
| CloudGatewayFilterSync   | 网关过滤器接口同步形态（用于对接同步 io）。v3.2.1 后支持                | 


* CloudGatewayFilter 示例（原始接口）

```java
@Component
public class CloudGatewayFilterImpl implements CloudGatewayFilter {
    @Override
    public Completable doFilter(ExContext ctx, ExFilterChain chain) {
        //代码写这儿
        return chain.doFilter(ctx);
    }
}
```

* CloudGatewayFilterMix 示例（虚拟类，组合网关接口）

```java
@Component
public class CloudGatewayFilterMixImpl extends CloudGatewayFilterMix {
    @Override
    public void register() {
        //配置写这儿 
        filter("StripPrefix=1");
        filter("AddRequestHeader=app.ver,1.0");
    }

    @Override
    public Completable doFilterDo(ExContext ctx, ExFilterChain chain) {
        //组合过滤器执行后的，代码写这儿
        return chain.doFilter(ctx);
    }
}
```

### 2、对接 solon-web 经典上下文接口

使用同步接口，可能会很伤害响应式的性能（这个要注意，不要做费时的事情）。ExContext 提供了一个转经典上下文接口的方法 `toContext()`，可满足特殊需要。比如和 sa-token 对接（仅供参考）：

```java
@Component
public class CloudGatewayFilterImpl implements CloudGatewayFilter {
    @Override
    public Completable doFilter(ExContext ctx, ExFilterChain chain) {
        Context ctx2 = ctx.toContext();
        
        //...处理代码

        return chain.doFilter(ctx);
    }
}

//如果需要使用 Context.current();
@Component
public class CloudGatewayFilterImpl implements CloudGatewayFilter {
    @Override
    public Completable doFilter(ExContext ctx, ExFilterChain chain) {
        return ContextHolder.currentWith(ctx.toContext(), () -> {
            //...处理代码

            return chain.doFilter(ctx);
        });
    }
}
```


### 3、对接同步 io 接口（v3.2.1 后支持）

使用同步 io 会卡住线程，这对网关引擎的事件循环器非常不友好。框架设计了两个对接的同步io接口的过滤器（<mark>旧版本的，可以直接复制代码</mark>）：

```java
//同步过滤器（会自动转异步）
@FunctionalInterface
public interface ExFilterSync extends ExFilter {
    @Override
    default Completable doFilter(ExContext ctx, ExFilterChain chain) {
        return Completable.create(emitter -> {
            //暂停接收流
            ctx.pause();

            //开始异步
            RunUtil.async(() -> {
                try {
                    //开始同步处理
                    boolean isContinue = doFilterSync(ctx);

                    if (isContinue) {
                        //继续
                        chain.doFilter(ctx).subscribe(emitter);
                    } else {
                        //结束
                        emitter.onComplete();
                    }
                } catch (Throwable ex) {
                    emitter.onError(ex);
                }
            });
        });
    }

    /**
     * 执行过滤同步处理（一般用于同步 io）
     *
     * @param ctx 上下文
     * @return 是否继续
     */
    boolean doFilterSync(ExContext ctx) throws Throwable;
}


//同步网关过滤器（会自动转异步）
@FunctionalInterface
public interface CloudGatewayFilterSync extends CloudGatewayFilter, ExFilterSync {

}
```

使用示例（对接一个 jdbc 签权服务。关于  sa-token 对接，参考后续的鉴权资料）

```java
@Component(index = -9)
public class AuthFilterSync implements CloudGatewayFilterSync {
    @Inject
    AuthJdbcService authService;

    @Override
    public boolean doFilterSync(ExContext ctx) throws Throwable {
        String userId = ctx.rawQueryParam("userId");
        //检测路径权限
        return authService.check(userId, ctx.rawPath());
    }
}
```

目前支持异步框架有：

* solon-net-httputils，支持异步 http
* solon-data-rx-sqlutils，支持异步 jdbc
* vert.x 的工具包
* projectreactor 的工具包



