目录
一、自定义断言工厂
二、自定义过滤器
1.自定义GatewayFilter
2.自定义GlobalFilter
二、Gateway源码剖析
Gateway作为SpringCloud体系中的网关,可以用来进行鉴权,安全控制,日志统一处理,易于监控,限流等。
一、自定义断言工厂
Gateway官方给我们能提供了很多种断言的方式,比如说通过路径、请求方法、cookie等等一系列的断言方式,我们可以参考一下官方的写法,然后就可以写出我们自己需要断言方式。
首先我们来到AbstractRoutePredicateFactory,这是断言父类接口的抽象实现类,因为我们需要自己定义断言的条件,所以在yml中解析到的参数会放到一个配置类当中,那这个构造方法其实就是将定义的配置类传到上面,这个抽象类的实现类其实就是各种断言工厂
首先我们定义一个类叫AccessTokenRoutePredicateFactory,因为遵循着约定大于配置的思想,所以我们在yml中配置的就会是 - AccessToken 开头的,并且我们需要继承AbstractRoutePredicateFactory并重写它的几个方法即可,下面是完整的代码
@Slf4j
@Component
public class AccessTokenRoutePredicateFactory extends AbstractRoutePredicateFactory {
private static final String Name = "headerName";
private static final String Value = "value";
public AccessTokenRoutePredicateFactory() {
super(Config.class);
}
@Override
public Predicate apply(Config config) {
return new Predicate() {
@Override
public boolean test(ServerWebExchange exchange) {
HttpHeaders headers = exchange.getRequest().getHeaders();
List list = headers.getOrDefault(config.headerName, Collections.emptyList());
if(list.size() != 1){
return false;
}
String value = list.get(0);
return value.equalsIgnoreCase(config.getValue());
}
};
}
@Override
public ShortcutType shortcutType() {
return ShortcutType.DEFAULT;
}
@Override
public List shortcutFieldOrder() {
return Arrays.asList(Name, Value);
}
@Data
public static class Config {
private String headerName;
private String value;
}
}
shortcutFieldOrder方法设置Config配置类的属性,会通过shortcutType设置的规则来进行设置,其中有好几种规则,DEFAULT是按照顺序依次赋值。
由于发送请求时存储在请求头之中,所以我们简单的获取比较一下即可完成逻辑
二、自定义过滤器
Gateway中的过滤器分为GatewayFilter(单一路由过滤器,也可以设置成全局)和GlobalFilter(全局过滤器)
1.自定义GatewayFilter
跟上面自定义断言工厂一样,需要创建一个遵循约定大于配置的过滤器实现AbstractGatewayFilterFactory,还是一样的设置shortcutType以及shortcutFieldOrder,下面是完成代码以及配置文件参数
@Slf4j @Component public class MyFilterGatewayFilterFactory extends AbstractGatewayFilterFactory{ private static String Name = "name"; private static String Value = "value"; public MyFilterGatewayFilterFactory() { super(Config.class); } @Override public GatewayFilter apply(Config config) { return new GatewayFilter() { @Override public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { log.info("MyFilterGatewayFilterFactory执行了,参数1={},参数2={}", config.getName(), config.getValue()); return chain.filter(exchange); } }; } @Override public ShortcutType shortcutType() { return ShortcutType.DEFAULT; } @Override public List shortcutFieldOrder() { return Arrays.asList(Name, Value); } @Data public static class Config { private String name; private String value; } }
#路由断言
predicates:
- Path=/driver
}
断言匹配成功之后,拿到相对应的handler,开始进行invoke,在FilteringWebHandler中可以看到先是获取了所有的全局过滤器,包括我们之前配置的也在,也是因为我们已经知道要走那个路由了,所以再获取当前路由的过滤器,并把它们整合到一起进行排序
排序完之后可以看到我们配置的主要放在了中间,也是根据我们设置的优先级进行排序,我们着重看下最后几个过滤器
另外看下它是如何设置这个责任链的,用了一个构造方法,index默认为0,每次取出filter,重新构造一下,并且index+1
在RouteToRequestUrlFilter中主要就是将我们的请求前面的域名和端口转换成我们要调用的服务,并且判断了是否需要进行负载均衡,然后传到下一个过滤器
在LoadBalancerClientFilter中会通过ribbon选择出相对应的实例,拿到实例的ip和端口就会将前面拼装好的url转换成ip+端口+请求路径以及参数的形式
在NettyRoutingFilter中会通过reactor-netty将数据进行发送
到这里,gateway的处理流程就大体讲完了。



