gateway中的局部过滤器_Spring-Cloud-Gateway之过滤器GatewayFilter

在Spring-Cloud-Gateway之请求处理流程文中我们了解最终网关是将请求交给过滤器链表进行处理,接下来我们阅读Spring-Cloud-Gateway的整个过滤器类结构以及主要功能

通过源码可以看到Spring-Cloud-Gateway的filter包中吉接口有如下三个,GatewayFilter,GlobalFilter,GatewayFilterChain,下来我依次阅读接口的主要实现功能。

GatewayFilterChain

类图

image

代码

/**

* 网关过滤链表接口

* 用于过滤器的链式调用

* Contract to allow a {@link WebFilter} to delegate to the next in the chain.

*

* @author Rossen Stoyanchev

* @since 5.0

*/

public interface GatewayFilterChain {

/**

* 链表启动调用入口方法

* Delegate to the next {@code WebFilter} in the chain.

* @param exchange the current server exchange

* @return {@code Mono} to indicate when request handling is complete

*/

Mono filter(ServerWebExchange exchange);

}

/**

* 网关过滤的链表,用于过滤器的链式调用

* 过滤器链表接口的默认实现,

* 包含2个构建函数:

* 1.集合参数构建用于初始化吧构建链表

* 2. index,parent参数用于构建当前执行过滤对应的下次执行的链表

*/

private static class DefaultGatewayFilterChain implements GatewayFilterChain {

/**

* 当前过滤执行过滤器在集合中索引

*/

private final int index;

/**

* 过滤器集合

*/

private final List filters;

public DefaultGatewayFilterChain(List filters) {

this.filters = filters;

this.index = 0;

}

/**

* 构建

* @param parent 上一个执行过滤器对应的FilterChain

* @param index 当前要执行过滤器的索引

*/

private DefaultGatewayFilterChain(DefaultGatewayFilterChain parent, int index) {

this.filters = parent.getFilters();

this.index = index;

}

public List getFilters() {

return filters;

}

/**

* @param exchange the current server exchange

* @return

*/

@Override

public Mono filter(ServerWebExchange exchange) {

return Mono.defer(() -> {

if (this.index < filters.size()) {

//获取当前索引的过滤器

GatewayFilter filter = filters.get(this.index);

//构建当前索引的下一个过滤器的FilterChain

DefaultGatewayFilterChain chain = new DefaultGatewayFilterChain(this, this.index + 1);

//调用过滤器的filter方法执行过滤器

return filter.filter(exchange, chain);

} else {

//当前索引大于等于过滤集合大小,标识所有链表都已执行完毕,返回空

return Mono.empty(); // complete

}

});

}

}

过滤器的GatewayFilterChain 执行顺序

通过GatewayFilter集合构建顶层的GatewayFilterChain

调用顶层GatewayFilterChain,获取第一个Filter,并创建下一个Filter索引对应的GatewayFilterChain

调用filter的filter方法执行当前filter,并将下次要执行的filter对应GatewayFilterChain传入。

GatewayFilter

类图

image

/**

* 网关路由过滤器,

* Contract for interception-style, chained processing of Web requests that may

* be used to implement cross-cutting, application-agnostic requirements such

* as security, timeouts, and others. Specific to a Gateway

*

* Copied from WebFilter

*

* @author Rossen Stoyanchev

* @since 5.0

*/

public interface GatewayFilter extends ShortcutConfigurable {

String NAME_KEY = "name";

String VALUE_KEY = "value";

/**

* 过滤器执行方法

* Process the Web request and (optionally) delegate to the next

* {@code WebFilter} through the given {@link GatewayFilterChain}.

* @param exchange the current server exchange

* @param chain provides a way to delegate to the next filter

* @return {@code Mono} to indicate when request processing is complete

*/

Mono filter(ServerWebExchange exchange, GatewayFilterChain chain);

}

网关过滤器接口,有且只有一个方法filter,执行当前过滤器,并在此方法中决定过滤器链表是否继续往下执行,接下来我们看下几个主要的功能实现类

OrderedGatewayFilter

/**

* 排序的网关路由过滤器,用于包装真实的网关过滤器,已达到过滤器可排序

* @author Spencer Gibb

*/

public class OrderedGatewayFilter implements GatewayFilter, Ordered {

//目标过滤器

private final GatewayFilter delegate;

//排序字段

private final int order;

public OrderedGatewayFilter(GatewayFilter delegate, int order) {

this.delegate = delegate;

this.order = order;

}

@Override

public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {

return this.delegate.filter(exchange, chain);

}

}

OrderedGatewayFilter实现类主要目的是为了将目标过滤器包装成可排序的对象类型。是目标过滤器的包装类

GatewayFilterAdapter

/**

* 全局过滤器的包装类,将全局路由包装成统一的网关过滤器

*/

private static class GatewayFilterAdapter implements GatewayFilter {

/**

* 全局过滤器

*/

private final GlobalFilter delegate;

public GatewayFilterAdapter(GlobalFilter delegate) {

this.delegate = delegate;

}

@Override

public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {

return this.delegate.filter(exchange, chain);

}

}

GatewayFilterAdapter实现类主要目的是为了将GlobalFilter过滤器包装成GatewayFilter类型的对应。是GlobalFilter过滤器的包装类

GlobalFilter

image

GlobalFilter 为请求业务以及路由的URI转换为真实业务服务的请求地址的核心过滤器,不需要配置,模式系统初始化时加载,并作用在每个路由上。

初始化加载,通过GatewayAutoConfiguration自动创建

GatewayAutoConfiguration 类

/**

* 全局过滤器,用户通过HttpClient转发请求

* @param httpClient

* @param headersFilters

* @return

*/

@Bean

public NettyRoutingFilter routingFilter(HttpClient httpClient,

ObjectProvider> headersFilters) {

return new NettyRoutingFilter(httpClient, headersFilters);

}

/**

* 全局的过滤器,用户将HttpClient客户端转发请求的响应写入到原始的请求响应中

* @param properties

* @return

*/

@Bean

public NettyWriteResponseFilter nettyWriteResponseFilter(GatewayProperties properties) {

return new NettyWriteResponseFilter(properties.getStreamingMediaTypes());

}

GatewayLoadBalancerClientAutoConfiguration 类

/**

* 全局过滤器,用于在通过负载均衡客户端选择服务实例信息

* @param client

* @return

*/

@Bean

@ConditionalOnBean(LoadBalancerClient.class)

public LoadBalancerClientFilter loadBalancerClientFilter(LoadBalancerClient client) {

return new LoadBalancerClientFilter(client);

}

GlobalFilter转换成GatewayFilter,并作用于每个路由上,在FilteringWebHandler实现

FilteringWebHandler类

/**

* 包装加载全局的过滤器,将全局过滤器包装成GatewayFilter

* @param filters

* @return

*/

private static List loadFilters(List filters) {

return filters.stream()

.map(filter -> {

//将所有的全局过滤器包装成网关过滤器

GatewayFilterAdapter gatewayFilter = new GatewayFilterAdapter(filter);

//判断全局过滤器是否实现了可排序接口

if (filter instanceof Ordered) {

int order = ((Ordered) filter).getOrder();

//包装成可排序的网关过滤器

return new OrderedGatewayFilter(gatewayFilter, order);

}

return gatewayFilter;

}).collect(Collectors.toList());

}

@Override

public Mono handle(ServerWebExchange exchange) {

//获取请求上下文设置的路由实例

Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);

//获取路由定义下的网关过滤器集合

List gatewayFilters = route.getFilters();

//组合全局的过滤器与路由配置的过滤器

List combined = new ArrayList<>(this.globalFilters);

//添加路由配置过滤器到集合尾部

combined.addAll(gatewayFilters);

//对过滤器进行排序

//TODO: needed or cached?

AnnotationAwareOrderComparator.sort(combined);

logger.debug("Sorted gatewayFilterFactories: "+ combined);

//创建过滤器链表对其进行链式调用

return new DefaultGatewayFilterChain(combined).filter(exchange);

}

loadFilters方法是将全局路由使用GatewayFilterAdapter包装成GatewayFilter

handle方法

获取当前请求使用的路由Route

获取路由配置的过滤器集合route.getFilters()

合并全过滤器与路由配置过滤器combined

对过滤器排序AnnotationAwareOrderComparator.sort

通过过滤器集合构建顶级链表DefaultGatewayFilterChain,并对其当前请求调用链表的filter方法。

==备注==:

Spring-Cloud-Gateway的过滤器接口分为两种:

GlobalFilter : 全局过滤器,不需要在配置文件中配置,作用在所有的路由上,最终通过GatewayFilterAdapter包装成GatewayFilterChain可识别的过滤器

GatewayFilter : 需要通过spring.cloud.routes.filters 配置在具体路由下,只作用在当前路由上或通过spring.cloud.default-filters配置在全局,作用在所有路由上

至此,网关过滤器的整个结构以及加载使用流程源码已经阅读完毕,下篇重点学习下路由配置的过滤器加载创建流程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Cloud Gateway 是基于 Spring WebFlux 框架开发的网关组件,提供了一种简单、轻量级的方式来构建微服务架构的路由和过滤器。 要实现局部过滤器,可以在 Gateway 配置文件为特定的路由添加过滤器。以下是一种实现方式: 1. 在 Spring Cloud Gateway 配置文件,定义一个路由规则并指定路由的 ID 和目标 URL,例如: ```yaml spring: cloud: gateway: routes: - id: my_route uri: http://example.com filters: - name: my_filter args: key: value ``` 2. 创建一个自定义的过滤器类,实现 `GatewayFilter` 接口,例如: ```java import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.http.HttpStatus; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; public class MyFilter implements GatewayFilter { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // 这里可以编写自定义的过滤逻辑 // 例如,根据请求头信息进行验证 String authToken = exchange.getRequest().getHeaders().getFirst("Authorization"); if (authToken == null || !authToken.startsWith("Bearer ")) { exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); } // 满足条件则继续执行后续过滤器或路由处理器 return chain.filter(exchange); } } ``` 3. 在 Spring Boot 应用程序,将自定义过滤器注册为一个 Bean,例如: ```java import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class GatewayConfig { @Bean public MyFilter myFilter() { return new MyFilter(); } } ``` 这样,在配置文件指定的路由上会应用自定义的过滤器。你可以根据实际需求编写不同的过滤器类来实现各种局部过滤器的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值