Spring Cloud Gateway 之过滤器链 个人心得和源码分析

本文主要探讨了Spring Cloud Gateway的过滤器链工作原理,包括GatewayFilter和GlobalFilter的区别,以及它们如何在过滤器链中发挥作用。关键类如GatewayAutoConfiguration、FilteringWebHandler和DefaultGatewayFilterChain的源码分析,揭示了过滤器的创建和执行流程。此外,文章还对比了SCG与Zuul的过滤器机制,强调了SCG在处理请求和响应上的优势。
摘要由CSDN通过智能技术生成

前言:
我其实就是想弄明白SpringCloud Gateway 中 Filter链表的构建原理和注入到Bean的时机,如果动态注入过滤器为Bean什么样的时机注入在默认情况下会生效,如果无法生效是因为什么原因,通过重写哪些方法类可以迫使生效。


过滤器和过滤器链

Spring Cloud Gateway根据作用范围划分为GatewayFilter和GlobalFilter。

  • GatewayFilter:需要通过spring.cloud.routes.filters配置在具体路由下,只作用在当前路由上或通过spring.cloud.default-filters配置在全局,作用在所有路由上
  • GlobalFilter:全局过滤器,不需要在配置文件中配置,作用在所有的路由上,最终通过GatewayFilterAdapter包装成GatewayFilterChain可识别的过滤器,它为请求业务以及路由的URI转换为真实业务服务的请求地址的核心过滤器,不需要配置,系统初始化时加载,并作用在每个路由上。

一些关键的类和接口

OrderGatewayFilter类实现了GatewayFilter和Ordered接口,将目标过滤器包装成可排序的对象类型,是目标过滤器的包装类。

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

FilteringWebHandler将GlobalFilter转化成GatewayFilter并生成DefaultGatewayFilterChain。

GatewayFilterChain网关过滤链表-接口

DefaultGatewayFilterChain 上面的实现类
网关过滤的链表,用于过滤器的链式调用。过滤器链表接口的默认实现。


源码分析

GatewayAutoConfiguration

配置类,将FilteringWebHandler注册为Bean

……
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMissing = true)
@EnableConfigurationProperties
@AutoConfigureBefore({
    HttpHandlerAutoConfiguration.class, WebFluxAutoConfiguration.class })
@AutoConfigureAfter({
    GatewayReactiveLoadBalancerClientAutoConfiguration.class,
		GatewayClassPathWarningAutoConfiguration.class })
@ConditionalOnClass(DispatcherHandler.class)
//这个配置类基本上加载了大部分Gateway的Bean
public class GatewayAutoConfiguration {
    
//上下文会扫描到这个配置类,然后扫描方法进行Bean的注入
//各种乱七八糟的Handler都是通过这个配置类注入为Bean的
	……	
	//根据获取配置类的方法扫描到这里,进行FilteringWebHandler的注入
	//在注入FilteringWebHandler之前,所有的过滤器已经注入过了
	/**或者说纯@Configuration的注入优先级没有那么高,就是不会是很早注入的
	/*没有哪种继承什么ContextAware的、BeanPostProcessor的、@Component的
	/*那样会先加载。
	/*所以说所有的过滤器已经在此之前实例化过了,
	/*这里就会将所有的GlobalFilter类型的Bean全部作为依赖注入进来
	/* 如果有过滤器在这个之后加入,那应该就不会生效了 )
	/* 因为那个过滤器链是final的,,,,,,后面会细说
	**/
	@Bean
	public FilteringWebHandler filteringWebHandler(List<GlobalFilter> globalFilters) {
   
		return new FilteringWebHandler(globalFilters);
	}

	@Bean
	public GlobalCorsProperties globalCorsProperties() {
   
		return new GlobalCorsProperties();
	}

	//路由处理 这里依赖一个webHandler,这个应该是路由下的过滤器
	@Bean
	public RoutePredicateHandlerMapping routePredicateHandlerMapping(FilteringWebHandler webHandler,
			RouteLocator routeLocator, GlobalCorsProperties globalCorsProperties, Environment environment) {
   
		return new RoutePredicateHandlerMapping(webHandler, routeLocator, globalCorsProperties, environment);
	}
	……

FilteringWebHandler

  • org.springframework.cloud.gateway.handler.FilteringWebHandler
package org.springframework.cloud.gateway.handler;

……
import org.springframework.web.server.WebHandler;

import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR;

/**
 * WebHandler that delegates to a chain of {@link GlobalFilter} instances and
 * {@link GatewayFilterFactory} instances then to the target {@link WebHandler}.
 *
 * @author Rossen Stoyanchev
 * @author Spencer Gibb
 * @since 0.1
 */
public class FilteringWebHandler implements WebHandler {
   

	protected static final Log logger = LogFactory.getLog(FilteringWebHandler.class);
	
	//全局过滤器链 final类型 初始定义之后就不能再改动了 好处是线程安全
	private final List<GatewayFilter> globalFilters;

	//通过配置类获取的所有GlobalFilter,成为一个final的链表
	public FilteringWebHandler(List<GlobalFilter> globalFilters) {
   
		this.globalFilters = loadFilters(globalFilters);
	}

	//将GlobaFilter转换为GatewayFilter串成链表
	private static List<GatewayFilter> loadFilters(List<GlobalFilter> 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());
	}

	//路由处理应该要走这个handle方法
	@Override
	public Mono<Void> handle(ServerWebExchange exchange) {
   
		//获得route
		Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
		//应该是获取路由下的过滤器
		List<GatewayFilter> gatewayFilters = route.getFilters();
		List<GatewayFilter> combined = new ArrayList<>(this.globalFilters);
		//将路由下的过滤器和全局过滤器合并
		combined.addAll(gatewayFilters);
		// TODO: needed or cached?
		//根据order进行排序
		AnnotationAwareOrderComparator.sort(combined);

		if (logger.isDebugEnabled()) {
   
			logger.debug("Sorted gatewayFilterFactories: " + combined);
		}
		
		//返回默认的网关过滤链
		return new DefaultGatewayFilterChain(combined).filter
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值