---
title: 如何实现Spring Gateway路由的动态加载和刷新？
description: Spring Cloud是一套优秀的微服务解决方案，堪称微服务架构集大成者。然而官方提供的API网关中，没有实现动态更新路由这个对大型复杂系统非常重要的功能。在此我们提供了一个完整的技术实现方式，希望能为有类似需求的同仁提供参考。
image: https://blog.advance.ai/hubfs/shutterstock_1935619246.jpg
---

[![wordmark-green-01-1](https://blog.advance.ai/hs-fs/hubfs/wordmark-green-01-1.png?width=446&height=54&name=wordmark-green-01-1.png "wordmark-green-01-1")](https://www.advanceai.com.cn/)

- 核心产品 
    - - AI 生物识别验证 
                  - [活体检测](https://www.advanceai.com.cn/liveness-detection)
                  - [人脸图像比对](https://www.advanceai.com.cn/face-comparison)
                  - [人脸搜索](https://www.advanceai.com.cn/face-search)
                  - [多维依据凭证人脸信用评分](https://www.advanceai.com.cn/facial-multi-loan-score)
          - AI 文档验证 
                  - [证件识别](https://www.advanceai.com.cn/id-document-recognition)
- 解决方案 
    - [数字身份验证](https://www.advanceai.com.cn/digital-identity-verification)
    - [视频身份验证](https://www.advanceai.com.cn/video-identification)
    - [更多部署方案](https://www.advanceai.com.cn/deployment-options)
- 行业应用 
    - [金融服务](https://www.advanceai.com.cn/financial-services)
    - [银行业](https://www.advanceai.com.cn/banking)
    - [旅游出行](https://www.advanceai.com.cn/travel)
    - [共享经济](https://www.advanceai.com.cn/sharing-economy)
    - [电子商务](https://www.advanceai.com.cn/e-commerce)
    - [金融科技](https://www.advanceai.com.cn/fintech)
- ADVANCE.AI研究 
    - [市场活动](https://www.advanceai.com.cn/events)
    - [白皮书和报告](https://www.advanceai.com.cn/whitepaper-reports_1)
    - [博客中心](https://www.advanceai.com.cn/blog)
- 关于我们 
    - [公司简介](https://www.advanceai.com.cn/about-advance-ai)
    - [安全团队](https://www.advanceai.com.cn/security-team)
    - [合作伙伴](https://www.advanceai.com.cn/partnership)
    - [新闻动态](https://www.advanceai.com.cn/company-news)
    - [加入我们](https://www.advanceai.com.cn/join-us)

- 核心产品 
    - 人工智能面部识别 
          - [活体检测](https://www.advance.ai/cn/liveness-detection)
          - [人脸图像比对](https://www.advance.ai/cn/face-comparison)
          - [人脸搜索](https://www.advance.ai/cn/face-search)
          - [欺诈人脸](https://www.advance.ai/cn/fraud-face)
          - [多维数据人脸信用评分](https://www.advance.ai/cn/facial-multi-loan-score)
    - 人工智能文件识别 
          - [证件识别](https://www.advance.ai/cn/id-document-recognition)
          - [身份证打码工具](https://www.advance.ai/cn/id-card-masking)
          - [证件打码](http://demo2019.test.yongsy.net/zhixinyin/index.html)
    - 人工智能文件处理 
          - [收据识别](https://www.advance.ai/cn/receipt-recognition)
          - [银行流水账单分析工具](https://www.advance.ai/cn/bank-statement-analyser)
    - 智慧零售货架识别 
          - [智慧零售](https://www.advance.ai/cn/smart-retailing)
- 解决方案 
    - [数字身份验证](https://www.advance.ai/cn/digital-identity-verification)
    - [视频身份验证](https://www.advance.ai/cn/video-identification)
    - [联合建模](https://www.advance.ai/cn/joint-modelling)
    - [更多部署方案](https://www.advance.ai/cn/deployment-options)
- 行业应用 
    - [金融服务](https://www.advance.ai/cn/financial-services)
    - [银行业](https://www.advance.ai/cn/banking)
    - [数字支付](https://www.advance.ai/cn/payment)
    - [医疗保健](https://www.advance.ai/cn/healthcare)
    - [旅游出行](https://www.advance.ai/cn/travel)
    - [共享经济](https://www.advance.ai/cn/sharing-economy)
    - [电子商务](https://www.advance.ai/cn/e-commerce)
    - [金融科技](https://www.advance.ai/cn/fintech)
    - [智慧物联](https://www.advance.ai/cn/internet-of-things)
- 领创研究 
    - [分享会](https://www.advance.ai/cn/events)
- 关于我们 
    - [公司简介](https://www.advance.ai/cn/about-advance-ai)
    - [安全团队](https://www.advance.ai/cn/security-team)
    - [新闻动态](https://www.advance.ai/cn/company-news)
    - [加入我们](https://www.advance.ai/cn/join-us)
    - [联系我们](https://www.advance.ai/cn/contact-us)

免费试用

中

- [EN](https://advance.ai/)

![](https://blog.advance.ai/hubfs/shutterstock_1935619246.jpg)

# 如何实现Spring Gateway路由的动态加载和刷新？

 Published by [Sample HubSpot User](https://blog.advance.ai/zh-cn/author/sample-hubspot-user) on  Mar 28, 2024, 2:29:03 PM

**作者：陆永剑  职位：后端工程师**

# **一、前言**

在微服务化过程中，客户端可能需要调用多个服务的接口才能完成一个业务需求。网关作为后端微服务的统一入口，利用路由转发可以方便客户端快速接入各个微服务。

Spring Gateway (以下简称gateway)路由配置默认情况下是写在配置文件中的，有一个新的服务接入时，需要修改配置文件，然后重启网关才能生效。然而目前更多的需求是通过提供可视化页面，在前端页面增删改来使网关路由动态生效。

结合实际业务需求，接下来从原理和实践两个方面介绍如何上述需求。

# **二、原理**

我们分两部分来说，先说动态加载，再说动态刷新。

## **2.1 动态加载**

要想实现动态加载，我们要先弄清楚gateway是如何加载现有的配置信息的。

目前配置路由主要有两种方式，一种是用yml配置文件，一种是写代码里。

1. `# yml配置文件形式`
2. `spring:`
3. `cloud:`
4. `gateway:`
5. `routes:`
6. `- id: v1`
7. `uri: http://xxx/v1`
8. `predicates:`
9. `- Path=/xxx`

```
 
```

1. `// 代码形式`
2. `@Bean`
3. `public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {`
4. `return builder.routes()```
5. `.route("v1", r -> r.path("/xxx")```
6. `.``uri("http://xxx/v1"))```
7. `.build();`
8. `}`

无论是yml还是代码，这些配置最终都是被封装到RouteDefinition对象中的。所有路由信息在系统启动时就被加载装配好了，并存到了内存里。

参考代码如下：

1. `//GatewayAutoConfiguration`
2. `@Bean`
3. `@ConditionalOnMissingBean`
4. `public PropertiesRouteDefinitionLocator`
5. `propertiesRouteDefinitionLocator(`
6. `GatewayProperties properties) {`
7. `return new PropertiesRouteDefinitionLocator(properties);`
8. `}`
9. `@Bean`
10. `@ConditionalOnMissingBean(RouteDefinitionRepository.class)`
11. `public InMemoryRouteDefinitionRepository`
12. `inMemoryRouteDefinitionRepository() {`
13. `return new InMemoryRouteDefinitionRepository();`
14. `}`
15. `//PropertiesRouteDefinitionLocator`
16. `public class PropertiesRouteDefinitionLocator implements`
17. `RouteDefinitionLocator {```
18. `private final GatewayProperties properties;```
19. `...```
20. `@Override```
21. `public Flux<RouteDefinition> getRouteDefinitions() {```
22. `return Flux.fromIterable(this.properties.getRoutes());```
23. `}`
24. `}`

重点类为 RouteDefinitionLocator,此接口有多个实现类，分别对应不同方式配置的路由方式。其中 RouteDefinitionRepository 是从存储器中(例如：mysql、redis 等)读取 RouteDefinition。可以结合 RouteDefinitionRepository 来实现动态路由加载。其他几种获取路由方式不是本文重点，暂不详说。

这样，我们就可以在网关启动时从一个动态数据源(数据库等，而非代码和配置文件)加载配置数据，并通过 RouteDefinitionRepository 的实现类 InMemoryRouteDefinitionRepository 加载为路由信息了。

## **2.2 动态刷新**

通过2.1我们找到了gateway从数据库加载路由的方式，但是还停留在gateway启动时加载数据的方式。接下来就看下如何实现在用户操作数据的时候就能完成gateway路由的刷新。

其实gateway是提供了刷新的事件的，那就是**RefreshRoutesEvent**。

参考代码如下：

1. `public class RefreshRoutesEvent extends ApplicationEvent {```
2. `/**```
3. `* Create a new ApplicationEvent.``  `
4. `* @param source the object on which the event initially occurred`
5. `(never {@code null})  ```
6. `*/  ```
7. `public RefreshRoutesEvent(Object source) {    ```
8. `super(source);  ```
9. `}`
10. `}` 

我们再来深挖下触发了RefreshRoutesEvent事件后，gateway是如何处理的。

1. `@Override`
2. `public void onApplicationEvent(ApplicationEvent event) {`
3. `...`
4. `else if (event instanceof RefreshRoutesEvent && routeLocator != null)`
5. `{  `
6. `// forces initialization  `
7. `routeLocator.ifAvailable(locator ->`
8. `locator.getRoutes().subscribe());  `
9. `}`
10. `}`

所以，我们的思路是，在用户操作路由数据，在数据保存到数据库之后，代码向gateway发送刷新事件就可以了。

# **三、实践**

![](https://blog.advance.ai/hs-fs/hubfs/image-png-Mar-28-2024-03-59-25-3195-AM.png?width=759&height=697&name=image-png-Mar-28-2024-03-59-25-3195-AM.png)

 

通过原理的分析，了解了网关从存储器中加载和动态刷新的机制。我们来整理下思路。

- 想加载路由数据到gateway内存中，需要调用InMemoryRouteDefinitionRepository 的save()方法。
- 想触发gateway的动态刷新，需要调用RefreshRoutesEvent事件。

接下来从这两点出发，一起开启实践之旅。

## **3.1 动态加载**

动态加载按照顺序可以分为三步，加载路由数据、组装路由、保存到gateway内存中。

## **3.1.1** **加载数据库数**

可以通过 feign 调用的方式读取数据，此步骤比较简单，不做详细的描述。

1. `List<GatewayRoute> routeList =`
2. `gatewayServiceClient.getApiRouteList().getData();`

### **3.1.2 ****组装路由、保存到gateway内存**

刚刚也分析到了RouteDefinition 是路由数据的核心。它大体包括三个部分，基本信息、断言(PredicateDefinition)、过滤器(FilterDefinition)。

接下来根据查询到的路由数据，进行gateway路由数据封装和保存。

1. `//路由封装`
2. `routeList.forEach(gatewayRoute -> {```
3.  
4. `//RouteDefinition结构`
5. `RouteDefinition definition = new RouteDefinition();```
6.  
7. `//设置基本信息`
8. `definition.setId(gatewayRoute.getRouteName());``    `
9. `definition.setUri(UriComponentsBuilder.fromUriString("lb://" +gatewayRoute.getServiceId()).build().toUri());    ``  ``  `
10.  
11. `//设置断言信息  ``  `
12. `List<PredicateDefinition> predicates = Lists.newArrayList();  ``  `
13. `PredicateDefinition predicatePath = new PredicateDefinition();  `
14. `Map<String, String> predicatePathParams = new HashMap<>(8);    ``  `
15. `predicatePath.setName("Path");  ``  `
16. `predicatePathParams.put("name", gatewayRoute.getRouteName());  ``  `
17. `predicatePathParams.put("pattern", gatewayRoute.getPath());  ``  `
18. `predicatePathParams.put("pathPattern", gatewayRoute.getPath());  `
19. `predicatePath.setArgs(predicatePathParams);  ``  `
20. `predicates.add(predicatePath);  ``  `
21. `definition.setPredicates(predicates);    ``  ``  `
22.  
23. `//设置过滤器信息  ``  `
24. `List<FilterDefinition> filters = filters(gatewayRoute);  ``  `
25. `if (!CollectionUtils.isEmpty(filters)) {    ``  `
26. `definition.setFilters(filters); ``  `
27. `}   ``  ``  `
28.  
29. `//重点，保存到gateway内存，其实是放在了Map<String, RouteDefinition> routes里  this.repository.save(Mono.just(definition)).subscribe();`
30. `});`

## **3.2 动态刷新**

动态刷新分为两步。第一步是提供公共方法，允许业务侧更新数据库之后调用刷新网关事件。第二步在gateway端接收到刷新网关事件后，调用RefreshRoutesEvent事件实现刷新。

### **3.2.1** **公共gateway刷新方法**

参考代码如下

1. `public class OpenRestTemplate extends RestTemplate {``  `
2. `/** ``  `
3. `* 刷新网关```
4. `*/```
5. `public void refreshGateway() {```
6. `publisher.publishEvent(```
7. `new`
8. `RefreshRemoteApplicationEvent(this,busProperties.getId(),null)```
9. `);```
10. `}`
11. `}`

### **3.2.2** ** 调用RefreshRoutesEvent事件实现刷新**

gateway接收到业务侧路由刷新事件后，调用 RefreshRoutesEvent 即可完成刷新动作。

参考代码如下

1. `/**```
2. `* 接收业务侧刷新事件```
3. `*```
4. `* @param event```
5. `*/`
6. `@Override`
7. `public void onApplicationEvent(RefreshRemoteApplicationEvent event) {```
8. `refresh();`
9. `}`
10. `/**```
11. `* 刷新路由```
12. `*```
13. `* @return```
14. `*/`
15. `public Mono<Void> refresh() {```
16. `//3.1加载路由的逻辑```
17. `this.loadRoutes();```
18. `//触发默认路由刷新事件,刷新缓存路由```
19. `this.publisher.publishEvent(new RefreshRoutesEvent(this));```
20. `return Mono.empty();`
21. }

# **四、结论**

结合实际业务需求，从原理和实践两个方面介绍了实现网关路由的动态加载和刷新方式。至此动态加载和刷新的功能就实现了，通过此功能，无论开发、测试、生产环境，都可以通过可视化页面快速的实现路由的动态修改，在配置速度和准确率上都可以得到很大提升。

[Back to Blog](https://blog.advance.ai/zh-cn)

## Related Articles

<https://blog.advance.ai/zh-cn/application-dubbo-service-0>

## [Dubbo3.0应用级服务注册原理](https://blog.advance.ai/zh-cn/application-dubbo-service-0)

 作者：周起仝 职位：后端工程师

[Read More](https://blog.advance.ai/zh-cn/application-dubbo-service-0)

<https://blog.advance.ai/zh-cn/distributed-websocket-service>

## [分布式WebSocket服务的挑战和一个简单实现](https://blog.advance.ai/zh-cn/distributed-websocket-service)

 作者：董礼 职位：后端工程师

[Read More](https://blog.advance.ai/zh-cn/distributed-websocket-service)

<https://blog.advance.ai/zh-cn/springcloud-architecture-breakpoint-debugging>

## [k8s集群中的springcloud架构如何丝滑的断点调试](https://blog.advance.ai/zh-cn/springcloud-architecture-breakpoint-debugging)

 作者：马铁强 职位：QA Lead

[Read More](https://blog.advance.ai/zh-cn/springcloud-architecture-breakpoint-debugging)

[![wordmark-white-01](https://blog.advance.ai/hs-fs/hubfs/AAI%20logo/wordmark-white-01.png?width=3809&name=wordmark-white-01.png "wordmark-white-01")](http://demo2019.test.yongsy.net/zhixincn/index.html)

- 友情链接 
    - [领创集团](https://www.advancegroup.com.cn/)
- 核心产品 
    - [AI 生物识别验证](https://www.advanceai.com.cn/liveness-detection)
    - [AI 文档验证](https://www.advanceai.com.cn/id-document-recognition)
- 解决方案 
    - [星鉴解决方案](https://www.advanceai.com.cn/xingjian)
    - [视频身份验证](https://www.advanceai.com.cn/video-identification)
    - [更多部署方案](https://www.advanceai.com.cn/deployment-options)
- 行业应用 
    - [金融服务](https://www.advanceai.com.cn/financial-services)
    - [银行业](https://www.advanceai.com.cn/banking)
    - [旅游出行](https://www.advanceai.com.cn/travel)
    - [共享经济](https://www.advanceai.com.cn/sharing-economy)
    - [电子商务](https://www.advanceai.com.cn/e-commerce)
    - [金融科技](https://www.advanceai.com.cn/fintech)
- 关于我们 
    - [公司简介](https://www.advanceai.com.cn/about-advance-ai)
    - [安全团队](https://www.advanceai.com.cn/security-team)
    - [合作伙伴](https://www.advanceai.com.cn/partnership)
    - [新闻动态](https://www.advanceai.com.cn/company-news)
    - [加入我们](https://www.advanceai.com.cn/join-us)

© 2024 ADVANCE.AI. 请参阅领创智信的[服务条款](https://beta.advance.ai/terms-of-service)和[隐私和安全声明](https://beta.advance.ai/privacy-security-statement)

[![Contact Icon](https://blog.advance.ai/hs-fs/hubfs/raw_assets/public/AdvanceIntelligence_October2020/images/icon1.png?width=180&name=icon1.png "Contact Icon")](https://info.advance.ai/cn-free-trial)

[![Message Icon](https://blog.advance.ai/hs-fs/hubfs/raw_assets/public/AdvanceIntelligence_October2020/images/icon2.png?width=180&name=icon2.png "Message Icon")](https://info.advance.ai/zh-cn/advance.ai-lianxiwomen)

![Back To Top](https://blog.advance.ai/hubfs/raw_assets/public/AdvanceIntelligence_October2020/images/icon4.png)