八、网关全局过滤器(CloudGatewayFilter)
CloudGatewayFilter 是 ExFilter 的扩展接口,主要是为了突出名字的专属性。使用时与 Filter 的区别:
- 最后要返回一个
Mono<Void>
。用于触发一个响应式订阅,从而让异步结束。 - 所有的异常,也要用
Mono.error(err)
返回
作用范围是网关全局。
1、网关全局过滤器
接口 | 说明 |
---|---|
CloudGatewayFilter | 原始网关接口 |
CloudGatewayFilterMix | 组合网关接口,可以方便组合 RoutePredicateFactory |
- CloudGatewayFilter 示例(原始接口)
@Component
public class CloudGatewayFilterImpl implements CloudGatewayFilter {
@Override
public Completable doFilter(ExContext ctx, ExFilterChain chain) {
//代码写这儿
return chain.doFilter(ctx);
}
}
- CloudGatewayFilterMix 示例(虚拟类,组合网关接口)
@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、示例:鉴权
此示例,检查有没有 "TOKEN" 的头信息,如果没有就 401 输出并中止。
@Component(index = -9) //index 为可选
public class AuthGatewayFilterImpl implements CloudGatewayFilter {
@Override
public Completable doFilter(ExContext ctx, ExFilterChain chain) {
String token = ctx.rawHeader("TOKEN");
if (token == null) {
//如果没有 TOKEN 表示失败
String resultStr = ONode.stringify(Result.failure(401, "签权失败"));
//ctx.newResponse().status(401);
ctx.newResponse().header("Content-Type", "application/json;charset=UTF-8");
ctx.newResponse().body(Buffer.buffer(resultStr));
return Completable.complete();
}
return chain.doFilter(ctx);
}
}
2、示例:全局异常处理
全局异常处理的过滤器,尽量放到最外层。这个风格跟同步的区别有点大。
@Component(index = -99)
public class CloudGatewayFilterImpl implements CloudGatewayFilter {
@Override
public Completable doFilter(ExContext ctx, ExFilterChain chain) {
return Completable.create(emitter -> {
chain.doFilter(ctx).subscribe(new CompletableSubscriber() {
@Override
public void onError(Throwable e) {
if (e instanceof StatusException) {
StatusException se = (StatusException) e;
ctx.newResponse().status(se.getCode());
emitter.onComplete();
} else {
ctx.newResponse().status(500);
emitter.onComplete();
}
}
@Override
public void onComplete() {
emitter.onComplete();
}
});
});
}
}