查看原文
其他

全网首发Spring Cloud Gateway 添加统一前缀功能

码农小胖哥 码农小胖哥 2019-09-11




1. 前言

今天学习一下Spring Cloud Gateway,就先再其他博客上逛了逛。遇到有java开发者在某博客问一个问题:Spring Cloud Gateway 如何添加统一的前缀? 当时没有在意,但是脑子里也带着这个问题看起了文档。随着慢慢了解Spring Cloud Gateway 这个问题就有了一点思路。


2.Gateway工作机制



这是官方文档上给的Spring Cloud Gateway工作流程图。大意上是客户端请求经过HandlerMapping的处理,如果匹配到路由(Router)就交给网关的web处理程序(Gateway Web Handler)来处理,经过一系列的调用过滤器链(肯定有责任链模式)后转发到被代理的服务执行真正的调用逻辑。


3. Gateway Handler Mapping

根据上图,我想找到所谓的Gateway Handler Mapping,看看是何方神圣。我找到了RoutePredicateHandlerMapping,并确定该类就是那个handler Mapping。依赖于Spring Webflux响应式web编程模型。核心方法是getHandlerInternal,通过该方法进行内部处理。

 


从代码上看 就是处理了端口关系后,在request放入一些gateway特定的attribute。然后走的一个寻找路由的方法。最后通过Mono.just(webHandler)交给了一个FilteringWebHandler类型的webHandler来处理了。我们先来关注lookupRoute方法,该方法摆明了就是寻找路由。该方法的代码不贴了。就是通过routeLocator.getRoutes()来加载所有的路由并通过断言(Predicate)来进行匹配。匹配到就交给FilteringWebHandler 走过滤器链。在我明白这个流程之后,脑子里那个问题就有了眉目。



4. FilteringWebHandler

该handler就是图中的Gateway Web Handler ,包含了一系列的GlobalFilter和GatewayFilter 来组成一个chain来处理前置和后置的逻辑,然后交给具体代理的服务。


5. 增加统一前缀的思路

 在以前我们知道zuul网关是可以添加一个统一前缀的。但是Spring Cloud Gateway是没有直接提供这个功能的。我已经搞清楚了Gateway的大致工作机制,甚至是一些细节。首先这个统一前缀肯定不能在断言中处理。断言是根据请求的个性化来找目的地路由的,而统一前缀是共性的。放在断言执行后也就是FilteringWebHandler来处理就更不合适了。因为断言执行在Filter之前。

有一个东西我们没有注意到。Spring Cloud Gateway的机制依赖于Spring Webflux框架的。经过查一些资料RoutePredicateHandlerMapping处理之前是可以设置WebFilter的。因此我找到了一个解决方案:在Gateway Client 和 Gateway Handler Mapping 之间定制一个WebFilter来处理统一前缀。


6. 思路实现

 

机制是这样的,请求带统一前缀请求经过我定制的WebFilter去掉前缀(当然你可以加一些其他你需要的逻辑)然后交给Gateway Handler Mapping处理。代码如下:



经过测试有效。


7. 总结

这里其实重点不是如何来实现这个功能,我想传达的是一个解决问题的思路。如何从框架的工作机制出发来分析你所需要解决的问题。找到那个合适的切入点。思路清晰了对于解决问题来说至关重要。其实我现在对Spring Cloud Gateway和Spring Webflux 都并不是很熟练,但是依然找了一个解决问题的方法。不知道你有没有更好的方法呢?相关代码已经上传到码云仓库:

https://gitee.com/felord/tino-cloud.git



   点击下方可查看其他干货▼        

最详细的自定义Spring Boot Starter开发教程

Spring Cloud 使用 Nacos 进行服务注册发现

快速理解Spring中的FactoryBean接口

微服务发现组件与配置管理组件NACOS环境快速体验

轻量级嵌入式数据库H2的愉快玩耍之旅



扫描二维码

   关注我

码农小胖哥





我就知道你在看!


Modified on

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存