网关全局过滤器(CloudGatewayFilter)
CloudGatewayFilter 是 ExFilter 的扩展接口,主要是为了突出名字的专属性。使用时与 Filter 的区别:
- 最后要返回一个
Completable
。用于触发一个响应式订阅,从而让异步结束。 - 所有的异常,也要用
Completable.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、对接 solon-web 同步接口(不建议使用)
使用同步接口,可能会很伤害响应式的性能(这个要注意)。ExContext 也提供了一个转同步接口的方法 toContext()
,可满足特殊需要。以与 sa-token 对接(仅供参考):
@Component
public class CloudGatewayFilterImpl implements CloudGatewayFilter {
@Override
public Completable doFilter(ExContext ctx, ExFilterChain chain) {
try {
//1.获取 web 经典同步接口;并设为当前上下文
Context ctx2 = ctx.toContext();
ContextHolder.currentSet(ctx2);
//2.对接同步处理(使用 sa-token 接口)
//new SaTokenFilter().doFilter(ctx2, ch->{});
StpUtil.checkLogin();
//3.检测是否要结束?
if (ctx2.isHeadersSent()) {
ctx2.flush();
return Completable.complete();
}
} catch (Throwable ex) {
return Completable.error(ex);
} finally {
ContextHolder.currentRemove();
}
return chain.doFilter(ctx);
}
}
示例:鉴权
此示例,检查有没有 "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);
}
}
示例:全局异常处理
全局异常处理的过滤器,尽量放到最外层。这个风格跟同步的区别有点大。
@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();
}
});
});
}
}