spring cloud gateway源码(一)请求时少一层的路径的源码分析

r有时我们用springcloudgateway做网关的时候,会发现调用的url少了一层,这个是什么做到的呢,我们就根据源码分析一下。

一、初始化

在GatewayDiscoveryClientAutoConfiguration类中创建了bean:DiscoveryLocatorProperties

	@Bean
	public DiscoveryLocatorProperties discoveryLocatorProperties() {
		DiscoveryLocatorProperties properties = new DiscoveryLocatorProperties();
		properties.setPredicates(initPredicates());
		properties.setFilters(initFilters());
		return properties;
	}

上面代码中有一行方法:properties.setFilters(initFilters()),返回了一个FilterDefinition

	public static List<FilterDefinition> initFilters() {
		ArrayList<FilterDefinition> definitions = new ArrayList<>();

		// add a filter that removes /serviceId by default
		FilterDefinition filter = new FilterDefinition();
		filter.setName(normalizeFilterFactoryName(RewritePathGatewayFilterFactory.class));
		String regex = "'/' + serviceId + '/(?<remaining>.*)'";
		String replacement = "'/${remaining}'";
		filter.addArg(REGEXP_KEY, regex);
		filter.addArg(REPLACEMENT_KEY, replacement);
		definitions.add(filter);

		return definitions;
	}

 当我们一个请求经过网关的时候,我们会经过getRouteDefinitions方法,这个方法中里面有这么一块代码,就是把注册到zookeeper上面的applicationName放到了filter中:

                    for (FilterDefinition original : this.properties.getFilters()) {
                    	FilterDefinition filter = new FilterDefinition();
                    	filter.setName(original.getName());
						for (Map.Entry<String, String> entry : original.getArgs().entrySet()) {
							String value = getValueFromExpr(evalCtxt, parser, instanceForEval, entry);
							filter.addArg(entry.getKey(), value);
						}
						routeDefinition.getFilters().add(filter);
					}

其中的appName等信息,是从别的服务注册到zookeeper上获取的,具体内容是从instance中取到的,instantce从zookeeper获取的信息内容如下:

ServiceInstance{name='upload', id='172.11.6.174', address='172.11.6.174', port=8016, sslPort=null, payload=ZookeeperInstance{id='application-1', name='upload', metadata={}}, registrationTimeUTC=1530273446489, serviceType=DYNAMIC, uriSpec=org.apache.curator.x.discovery.UriSpec@6c2ac0dc, enabled=true}

 关于获取zookeeper的instance我们放到另一篇文章里面。

处理完后我们就放到了routeDifinition中返回,此时serviceId就放在了routDefinition中。

然后在RouteDefinitionRouteLocator中的loadGatewayFilters方法中,执行了GatewayFilterFactory的apply()方法,实际上用的是RewritePathGatewayFilterFactory,入参的Config就是RewritePathGatewayFilterFactory的内部类Config

	@Override
	public GatewayFilter apply(Config config) {
		String replacement = config.replacement.replace("$\\", "$");
		return (exchange, chain) -> {
			ServerHttpRequest req = exchange.getRequest();
			addOriginalRequestUrl(exchange, req.getURI());
			String path = req.getURI().getRawPath();
			String newPath = path.replaceAll(config.regexp, replacement);

			ServerHttpRequest request = req.mutate()
					.path(newPath)
					.build();

			exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, request.getURI());

			return chain.filter(exchange.mutate().request(request).build());
		};
	}

在这段apply方法中,regexp为:/application/(?<remaining>.*)   replacement为:/${remaining},然后将获取的newPath放到了Request上,并且放入了GATEWAY_REQUEST_URL_ATTR属性,后面请求就是根据rewrite中处理的新的path进行请求了 

 

扫描二维码关注公众号,回复: 2784444 查看本文章

猜你喜欢

转载自blog.csdn.net/lz710117239/article/details/81122838
今日推荐