简单阐述实现的步骤:
这里实现gateway的动态路由,将路由数据存储到数据库中,进行持久化
实现的逻辑
1、一个完完整的路有信息基本包括一下信息
RouteDefinition
PredicateDefinition
FilterDefinition
2、参照gateway给提供的对gateway进行Crud的api的实现
GatewayControllerEndpoint中的逻辑从而实现动态路由
3、实现将gateway的路由信息持久化到数据库中
实现步骤
0.1 gateway 服务启动的时候 通过监听服务的启动从数据库加载路由信息
0.2 对gateway 服务的路由信息进行curd操作的时候,先持久化数据库,持久化成功然后更新gateway服务对路由的缓存
从而实现对网关路由的curd操作
下边上代码:
首先项目的结构
代码讲解:
pom的依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cloud2022-anli</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-gateway-dynamic</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
</dependencies>
</project>
``
网关动态路由的核心类 ,处理路由的curd,实现接口ApplicationEventPublisherAware 用来支持Spring事件的发布,更新gateway服务内存中的路由信息
接口 ApplicationRunner 用来支持当gateway服务启动的时候从数据库加载路由信息
```java
package com.gatewaydy.gatwayhandler;
import com.alibaba.fastjson.JSON;
import com.gatewaydy.entity.GatewayInfo;
import com.gatewaydy.service.GatewayService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
import java.util.List;
/**
* @author: LCG
* @date: 2022-10-27 12:24:44
* @description: 动态路由的处理类,在这个类中通过实现ApplicationRunner接口的run方法,在gateway项目启动的时候
* 从数据库读取 路由信息然后添加到 gateway服务的内存中,同时如果对路由进行curd操作的时候先更新持久化的信息然后再更新
* gateway服务中的路由信息,通过gateway提供的RefreshRoutesEvent事件刷新gateway内存中的路由信息
**/
@Component
@Slf4j
public class GatewayServiceHandler implements ApplicationEventPublisherAware, ApplicationRunner {
@Autowired
private GatewayService gatewayService;
private RouteDefinitionWriter routeDefinitionWriter;
private ApplicationEventPublisher applicationEventPublisher;
public GatewayServiceHandler(RouteDefinitionWriter routeDefinitionWriter) {
this.routeDefinitionWriter = routeDefinitionWriter;
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher=applicationEventPublisher;
}
/**
* @author: LCG
* @date: 2022-10-27 13:31:26
* @description: 添加路由信息
*/
public String addRoutes(RouteDefinition routeDefinition){
//保存路由信息到数据库
int i = gatewayService.saveRoute(routeDefinition);
if(i==1){
//存入内存中
routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
log.info("---存入-gateway服务的缓存中-{}",routeDefinition);
//刷新gateway的缓存
this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
log.info("---存入-gateway服务的缓存中-执行事件刷新");
return "ok";
}else{
log.info("---存入-db和gateway缓存失败");
return "faile";
}
}
/**
* @author: LCG
* @date: 2022-10-27 12:42:43
* @description: 容器启动的时候加载持久化的路由数据
*/
@Override
public void run(ApplicationArguments args) throws Exception {
log.info("gateway启动加载数据中的路由信息");
List<GatewayInfo> gatewayInfoList = gatewayService.getGatewayInfoList("g1");
log.info("查询到的gateway路由数据={}",gatewayInfoList);
if(gatewayInfoList!=null){
for (GatewayInfo gatewayInfo : gatewayInfoList) {
RouteDefinition routeDefinition = JSON.parseObject(gatewayInfo.getGatewayInfo(), RouteDefinition.class);
routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
}
}
}
}```
剩下的代码请大家在这里获取源代码
https://gitee.com/zbf-lcg/zbf2022.git
实现持久化路由信息到redis的话请大家自行将在数据库操作路由信息的代码换成redis中操作路由信息即可,这里不再写代码演示
## 感谢大家阅读,大家看过有问题请留言!