1、目标
本篇文章的主要目标是找到网关过滤器找不到的原因,并进行源码跟踪
2、报错现象
设置网关过滤器,继承AbstractGatewayFilterFactory,重写apply方法
@Component
@Log4j2
public class VerifyGatewayFilterFactory extends AbstractGatewayFilterFactory<Object> {
@Override
public GatewayFilter apply(Object config) {
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
log.info("request: " + request);
log.info("网关过滤器VerifyGatewayFilter");
return chain.filter(exchange);
};
}
}
在Nacos的配置文件设置demo04-payment-service服务的路由转发
- id: demo04-payment
uri: lb://demo04-payment-service
predicates:
- Path=/paymentPath/**
filters:
- VerifyGatewayFilterFactory
- RewritePath=/paymentPath(?<segment>/?.*), $\{segment}
启动服务后会抛出异常:
java.lang.IllegalArgumentException: Unable to find GatewayFilterFactory with name VerifyGatewayFilterFactory
at org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator.loadGatewayFilters(RouteDefinitionRouteLocator.java:130) ~[spring-cloud-gateway-server-3.0.3.jar:3.0.3]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Assembly trace from producer [reactor.core.publisher.FluxMapFuseable] :
reactor.core.publisher.Flux.map(Flux.java:6091)
org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator.getRoutes(RouteDefinitionRouteLocator.java:95)
Error has been observed at the following site(s):
|_ Flux.map ⇢ at org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator.getRoutes(RouteDefinitionRouteLocator.java:95)
|_ Flux.map ⇢ at org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator.getRoutes(RouteDefinitionRouteLocator.java:107)
|_ Flux.flatMapSequential ⇢ at org.springframework.cloud.gateway.route.CompositeRouteLocator.getRoutes(CompositeRouteLocator.java:34)
|_ Flux.sort ⇢ at org.springframework.cloud.gateway.route.CachingRouteLocator.fetch(CachingRouteLocator.java:61)
|_ Flux.sort ⇢ at org.springframework.cloud.gateway.route.CachingRouteLocator.fetch(CachingRouteLocator.java:61)
|_ Flux.sort ⇢ at org.springframework.cloud.gateway.route.CachingRouteLocator.fetch(CachingRouteLocator.java:61)
|_ Flux.collect ⇢ at org.springframework.cloud.gateway.route.CachingRouteLocator.onApplicationEvent(CachingRouteLocator.java:81)
Stack trace:
at org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator.loadGatewayFilters(RouteDefinitionRouteLocator.java:130) ~[spring-cloud-gateway-server-3.0.3.jar:3.0.3]
at org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator.getFilters(RouteDefinitionRouteLocator.java:176) ~[spring-cloud-gateway-server-3.0.3.jar:3.0.3]
at org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator.convertToRoute(RouteDefinitionRouteLocator.java:117) ~[spring-cloud-gateway-server-3.0.3.jar:3.0.3]
3、源码跟踪
根据报错信息可以跟踪网关过滤器的源码
进入RouteDefinitionRouteLocator构造器
初始化RouteDefinitionRouteLocator对象会遍历gatewayFilterFactories这个list集合,然后将GatewayFilterFactory对象的name作为map的key,将GatewayFilterFactory对象作为map的value,存放到map中
进入factory的name()方法
该方法会将容器中VerifyGatewayFilterFactory网关过滤器对象的类名去除GatewayFilterFactory的类名,因此map的key会保存Verify作为网关过滤器的name
这里Class类对象的getSimpleName方法会返回类名
replace("xxx’, “”)会将这个字符串的xxx替换成空,即删除xxx字符串
该方法会解析Nacos配置文件中的网关路由RouteDefinition对象,其中filters是Nacos配置文件中的网关过滤器的名字VerifyGatewayFilterFactory和RewritePath
然后执行loadGatewayFilters方法
该方法会从gatewayFilterFactories这个map中根据key=VerifyGatewayFilterFactory得到value是null,因为gatewayFilterFactories这个map保存了Verify这个key,也就是说容器中的map的key是去除GatewayFilterFactory的名字,而Nacos配置文件中设置网关过滤器的名字是VerifyGatewayFilterFactory,因此从map获取不到VerifyGatewayFilterFactory对象就会报错:
Unable to find GatewayFilterFactory with name VerifyGatewayFilterFactory
4、解决办法
将网关过滤器的名字设置成Verify
这样就可以找到网关过滤器,启动服务正常
网关配置是
spring:
cloud:
gateway:
routes:
- id: demo04-order
uri: lb://demo04-order-service
predicates:
- Path=/orderPath/**
filters:
- RewritePath=/orderPath(?<segment>/?.*), $\{segment}
- id: demo04-payment
uri: lb://demo04-payment-service
predicates:
- Path=/paymentPath/**
filters:
- Verify
- RewritePath=/paymentPath(?<segment>/?.*), $\{segment}
执行localhost:8080/paymentPath/payment/m1,测试网关过滤器是否生效
可以看到访问网关的paymentPath路径会经过网关过滤器VerifyGatewayFilterFactory,因为网关路由转发paymentPath路径配置了Verify
执行localhost:13087/orderPath/order/f1,不会经过网关过滤器VerifyGatewayFilterFactory,因为网关路由转发orderPath路径没有配置Verify