SpringCloudGateway的两种使用方式,结合StripPrefixFilterFilterFactory和PrefixPathGatewayFilterFactory核心代码

Gateway的作用

Spring Cloud Gateway 组件的核心是通过一系列的过滤器,通过这些过滤器可以将客户端发送的请求转发(路由)到对应的微服务。

核心配置

  • route:由id、uri、predicate、filters组成
  • predicate:即断言,匹配路由的部件,支持正则表达式
  • filters:过滤器,在断言匹配后执行,对路由信息进行操作,也可以操作header、参数等

方法一(配置文件)

1. 依赖

注意:由于gateway默认依赖webflux,所以不需要加入springboot-web的依赖,否则会报错;
同时,本次实验使用的是Zookeeper作为注册中心,所以不需要加入eureka-client的依赖,否则启动报错



<dependency>
	<groupId>org.springframework.cloudgroupId>
	<artifactId>spring-cloud-starter-gatewayartifactId>
dependency>

<dependency>
	<groupId>org.springframework.cloudgroupId>
	<artifactId>spring-cloud-starter-zookeeper-discoveryartifactId>
	
	<exclusions>
		<exclusion>
			<groupId>org.apache.zookeepergroupId>
			<artifactId>zookeeperartifactId>
		exclusion>
	exclusions>
dependency>
<dependency>
	<groupId>org.springframework.cloudgroupId>
	<artifactId>spring-cloud-starter-zookeeper-configartifactId>
dependency>

2. yml

server:
  port: 9527

spring:
  profiles:
	active:
  application:
	name: springcloud-gateway
  cloud:
	gateway:
	  routes:
		- id: devilvan-route-strip
		  uri: lb://devilvan-caches/caches
		  predicates:
			# 匹配满足条件的路由
			- Path=/caches/cachesController/**
		  # Predicate断言后就会执行过滤器
		  filters:
			# StripPrefix:将Path匹配的第1段路由(/caches)舍弃,真正的匹配路由为:/cachesController/**
			- StripPrefix=1
		- id: devilvan-route-prefix
		  uri: lb://devilvan-caches/caches
		  predicates:
			- Path=/**
		  filters:
			# PrefixPath:给匹配的Path的前面补充一个前缀,若输入路由:playCaffeineCaches
			# 则真正的匹配路由为:/cachesController/playCaffeineCaches
			- PrefixPath=/cachesController
	zookeeper:
	  connect-string: localhost:2181
	  enabled: true
	  connection-timeout: 60000

3. 参数、细节

  1. routes可以设置多个,通过uri来区分不同的服务,也可由此来配置不同的predicates和filters
  2. predicates即断言,可配置的参数来自RoutePredicateFactory的实现类,例如:PathRoutePredicateFactory
  3. filters即过滤器,可配置的参数来自GatewayFilterFactory,例如:StripPrefixGatewayFilterFactory
  4. uri即经过断言和过滤器后,最终被转发到的IP+端口,也可以是一组服务

4. StripPrefix和PrefixPath

StripPrefix作用是:忽略当前路由的第n段路由,结合part使用
PrefixPath作用是:在当前路由的最前端加上一个自定义路由

5. 测试

原访问路由:localhost:8077/cachesController/playCaffeineCaches
添加如上配置的网关后的路由:
StripPrefix=1
http://localhost:9527/caches/cachesController/playCaffeineCaches => localhost:8077/cachesController/playCaffeineCaches

PrefixPath=/cacheController
http://localhost:9527/playCaffeineCaches == localhost:8077/cachesController/playCaffeineCaches

方法二(配置类)

此方法通过编码形式的配置类提供网关服务,效果和以上配置文件效果一样

核心部分为PredicateFactory和FilterFactory的运用,且都需要结合各自工厂的Config内部类使用,最终通过routes()方法连接起来

@Configuration
public class GatewayConfig {
	@Bean
	public RouteLocator routes(RouteLocatorBuilder builder) {
		return builder.routes()
				.route("devilvan-route-strip", new Function<PredicateSpec, Route.AsyncBuilder>() {
					@Override
					public Route.AsyncBuilder apply(PredicateSpec predicateSpec) {
						/*
						* predicate
						* 1. 创建匹配的断言对应的工厂,例如:yml配置中的path == PathRoutePredicateFactory
						* 2. 通过工厂的newConfig产生对应的配置类对象,这个对象里可以set的属性就是可配置的参数
						*/
						PathRoutePredicateFactory pathRoutePredicateFactory = new PathRoutePredicateFactory();
						PathRoutePredicateFactory.Config pathRouteConfig = pathRoutePredicateFactory.newConfig();
						List<String> pattern4StripPrefix = new ArrayList<>();
						pattern4StripPrefix.add("/caches/cachesController/**");
						pathRouteConfig.setPatterns(pattern4StripPrefix);
						/*
						* filters
						* 1. filters在匹配断言后执行
						* 2. 创建过滤器工厂,例如:yml配置中的StripPrefix == StripPrefixGatewayFilterFactory
						* 3. 通过工厂的newConfig创建配置类,在配置类中给可配置参数赋值
						* */
						StripPrefixGatewayFilterFactory stripPrefixGatewayFilterFactory = new StripPrefixGatewayFilterFactory();
						StripPrefixGatewayFilterFactory.Config stripConfig = stripPrefixGatewayFilterFactory.newConfig();
						stripConfig.setParts(1);
						stripPrefixGatewayFilterFactory.apply(stripConfig);
						/*
						* 组装predicate和filter
						* 1. 即将predicate和filters连接起来
						* 2. 通过PredicateSpec对象的predicate、filters等方法将断言和过滤器等联系起来
						* 3. 内容基本都是:factory.apply(factory.config)
						* */
						predicateSpec.predicate(pathRoutePredicateFactory.apply(pathRouteConfig))
								.filters(new Function<GatewayFilterSpec, UriSpec>() {
									@Override
									public UriSpec apply(GatewayFilterSpec gatewayFilterSpec) {
										return gatewayFilterSpec.filter(stripPrefixGatewayFilterFactory.apply(stripConfig));
									}
								});
						return predicateSpec.uri("lb://devilvan-caches/caches");
					}
				})
				.route("devilvan-route-prefix", new Function<PredicateSpec, Route.AsyncBuilder>() {
					@Override
					public Route.AsyncBuilder apply(PredicateSpec predicateSpec) {
						PathRoutePredicateFactory pathRoutePredicateFactory = new PathRoutePredicateFactory();
						PathRoutePredicateFactory.Config pathRouteConfig = pathRoutePredicateFactory.newConfig();
						List<String> pattern4PrefixPath = new ArrayList<>();
						pattern4PrefixPath.add("/**");
						pathRouteConfig.setPatterns(pattern4PrefixPath);
						// filters
						PrefixPathGatewayFilterFactory prefixPathGatewayFilterFactory = new PrefixPathGatewayFilterFactory();
						PrefixPathGatewayFilterFactory.Config prefixPathConfig = prefixPathGatewayFilterFactory.newConfig();
						prefixPathConfig.setPrefix("/cachesController");
						// 组装predicate和filter
						predicateSpec.predicate(pathRoutePredicateFactory.apply(pathRouteConfig))
								.filters(new Function<GatewayFilterSpec, UriSpec>() {
									@Override
									public UriSpec apply(GatewayFilterSpec gatewayFilterSpec) {
										return gatewayFilterSpec.filter(prefixPathGatewayFilterFactory.apply(prefixPathConfig));
									}
								});
						return predicateSpec.uri("lb://devilvan-caches/caches");
					}
				})
				.build();
	}
}

StripPrefixFilterFactory核心代码

SpringCloudGateway的两种使用方式,结合StripPrefixFilterFilterFactory和PrefixPathGatewayFilterFactory核心代码_第1张图片

PrefixPathGatewayFilterFactory

SpringCloudGateway的两种使用方式,结合StripPrefixFilterFilterFactory和PrefixPathGatewayFilterFactory核心代码_第2张图片

你可能感兴趣的:(SpringCloud,spring,cloud,java,前端)