public int getOrder() {
return 1;
}
}
定义GatewayFilter过滤器
注意:这里为了简单,直接继承自AbstractNameValueGatewayFilterFactory,实际使用看自己需求选择继承类
@Component
public class FaGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
@Override
public GatewayFilter apply(NameValueConfig config) {
return (exchange, chain) -> {
System.out.println(“Fa”);
return chain.filter(exchange);
};
}
}
@Component
public class FbGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
@Override
public GatewayFilter apply(NameValueConfig config) {
return (exchange, chain) -> {
System.out.println(“Fb”);
return chain.filter(exchange);
};
}
}
@Component
public class FcGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
@Override
public GatewayFilter apply(NameValueConfig config) {
return (exchange, chain) -> {
System.out.println(“Fc”);
return chain.filter(exchange);
};
}
}
GatewayFilter类型的过滤器,只在配置了此过滤器的路由服务上生效,所以需要加到路由配置上,"="后面的n,v为NameValueConfig里面的值,这里随便写一下。
routes:
- id: 用户服务
uri: lb://user-service
predicates:
- Path=/user-service/**
filters:
-
Fa=n, v
-
Fc=n, v
-
Fb=n, v
结果输出
Ga 1
Gc 1
Fa
Gb 2
Fc
Fb
源码分析
服务启动时,org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator会将路由中配置了的过滤器加载到路由的过滤器集合中,并封装Order值。
private List loadGatewayFilters(String id, List filterDefinitions) {
List filters = (List)filterDefinitions.stream().map((definition) -> {
// 从过滤器工厂中取出配置了的过滤器封装到路由的过滤器集合中
GatewayFilterFactory factory = (GatewayFilterFactory)this.gatewayFilterFactories.get(definition.getName());
if (factory == null) {
throw new IllegalArgumentException("Unable to find GatewayFilterFactory with name " + definition.getName());
} else {
Map<String, String> args = definition.getArgs();
if (this.logger.isDebugEnabled()) {
this.logger.debug("RouteDefinition " + id + " applying filter " + args + " to " + definition.getName());
}
Map<String, Object> properties = factory.shortcutType().normalize(args, factory, this.parser, this.beanFactory);
Object configuration = factory.newConfig();
ConfigurationUtils.bind(configuration, properties, factory.shortcutFieldPrefix(), definition.getName(), this.validator);
GatewayFilter gatewayFilter = factory.apply(configuration);
if (this.publisher != null) {
this.publisher.publishEvent(new FilterArgsEvent(this, id, properties));
}
return gatewayFilter;
}
}).collect(Collectors.toList());
ArrayList ordered = new ArrayList(filters.size());
// 遍历过滤器集合,封装成带Order值的过滤器集合
for(int i = 0; i < filters.size(); ++i) {
GatewayFilter gatewayFilter = (GatewayFilter)filters.get(i);
if (gatewayFilter instanceof Ordered) {
ordered.add(gatewayFilter);
} else {
// 从1开始递增生成Order值
ordered.add(new OrderedGatewayFilter(gatewayFilter, i + 1));
}
}
return ordered;
}
请求网关时,org.springframework.cloud.gateway.handler.FilteringWebHandler会将路由中的过滤器和全局过滤器合并封装排序,生成完整的过滤器链。
public Mono handle(ServerWebExchange exchange) {
Route route = (Route)exchange.getRequiredAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
List gatewayFilters = route.getFilters();
List combined = new ArrayList(this.globalFilters);
// 将路由中的过滤器集合添加到全局过滤器集合
combined.addAll(gatewayFilters);
// 排序算法
AnnotationAwareOrderComparator.sort(combined);
if (logger.isDebugEnabled()) {
logger.debug("Sorted gatewayFilterFactories: " + combined);
}
return (new FilteringWebHandler.DefaultGatewayFilterChain(combined)).filter(exchange);
}
debug调试
通过debug调试,排序前的过滤器顺序,可以看出路由中配置的GatewayFilter类型过滤器是追加在GlobalFilter过滤器集合后面,并且可以看出GatewayFilter类型的过滤器Order值是1、2、3。
排序后,按照Order值排序,GlobalFilter类型过滤器的Order值相同时,按文件名排序,GatewayFilte和GlobalFilterr类型过滤器的Order值相同时也是排在GlobalFilter下面。
技术学习总结
学习技术一定要制定一个明确的学习路线,这样才能高效的学习,不必要做无效功,既浪费时间又得不到什么效率,大家不妨按照我这份路线来学习。
最后面试分享
大家不妨直接在牛客和力扣上多刷题,同时,我也拿了一些面试题跟大家分享,也是从一些大佬那里获得的,大家不妨多刷刷题,为金九银十冲一波!
路线来学习。
[外链图片转存中…(img-9bqxHCGH-1714453793824)]
[外链图片转存中…(img-Y5KxMn60-1714453793825)]
[外链图片转存中…(img-AeARCg5s-1714453793825)]
最后面试分享
大家不妨直接在牛客和力扣上多刷题,同时,我也拿了一些面试题跟大家分享,也是从一些大佬那里获得的,大家不妨多刷刷题,为金九银十冲一波!
[外链图片转存中…(img-renRs7H7-1714453793825)]
[外链图片转存中…(img-ZK3V141T-1714453793826)]