SpringCloud Gateway 利用 Mysql 实现动态路由的方法

 更新时间:2021年02月19日 09:54:39   作者:稀土掘金  
这篇文章主要介绍了SpringCloud Gateway 利用 Mysql 实现动态路由的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

需求描述

标准网关动态路由功能是重要的一环,将路由、断言以及过滤器信息,持久化到 Mysql 中,通过配置后台页面实现路由、断言、以及过滤器等配置的增删改查。

Spring Cloud Gateway 路由及黑白名单实现背景 Spring Cloud 路由API

Spring Cloud Gateway 通过定义 RouteDefinitionRepository 来实现动态路由.

//保存路由缓存
public interface RouteDefinitionWriter {

  Mono<Void> save(Mono<RouteDefinition> route);

  Mono<Void> delete(Mono<String> routeId);

}
//获取路由缓存
public interface RouteDefinitionLocator {

  Flux<RouteDefinition> getRouteDefinitions();

}

Spring Cloud 配置文件路由加载方式

public class PropertiesRouteDefinitionLocator implements RouteDefinitionLocator {

  private final GatewayProperties properties;

  public PropertiesRouteDefinitionLocator(GatewayProperties properties) {
   this.properties = properties;
  }

  @Override
  public Flux<RouteDefinition> getRouteDefinitions() {
   return Flux.fromIterable(this.properties.getRoutes());
  }

}

Spring Cloud 黑白名 FilterFactory

利用 Spring Cloud Gateway 声明的一个工厂接口 GatewayFilterFactory, 定义 黑白名单过滤器

BlacklistGatewayFilterFactory 类图

WhitelistGatewayFilterFactory 类图

动态路由设计 Spring Cloud Gateway 路由实体类

Spring Cloud Gateway 通过定义 RouteDefinition 类装载路由信息。

package org.springframework.cloud.gateway.route;

public class RouteDefinition {

  //路由 ID
  @NotEmpty
  private String id = UUID.randomUUID().toString();

  //断言数组
  @NotEmpty
  @Valid
  private List<PredicateDefinition> predicates = new ArrayList<>();

  //过滤器数组
  @Valid
  private List<FilterDefinition> filters = new ArrayList<>();

  // 路由地址
  @NotNull
  private URI uri;

  // 路由顺序
  private int order = 0;
}

数据库设计

路由表

drop table if exists gateway_route_t;

create table if not exists gateway_route_t
(
  ID     int auto_increment primary key,
  ROUTE_ID  varchar(255) not null comment '路由ID',
  ROUTE_ORDER int default 0 null comment '路由顺序',
  URI     varchar(255) not null comment '路由路径',
  VALID    int default 1 not null comment '是否有效:0-无效,1-有效',
  CREATE_USER varchar(200) null comment '创建人',
  CREATE_TIME datetime   null comment '创建时间',
  UPDATE_USER varchar(200) null comment '修改人',
  UPDATE_TIME datetime   null comment '修改时间',
  constraint idx_ROUTE_ID_index unique (ROUTE_ID)
) comment '网关路由信息表' charset = utf8;

路由参数表

drop table if exists gateway_route_param_t;

create table if not exists gateway_route_param_t
(
  ID     int auto_increment primary key,
  ROUTE_ID  varchar(255) not null comment '路由ID',
  PARAM_NAME varchar(255) not null comment '参数name',
  PARAM_KEY  varchar(255) not null comment '参数 key',
  PARAM_VALUE varchar(255) not null comment '参数 value',
  TYPE    int      not null comment '参数类型,1为 predicate,2为过 filter',
  VALID    int default 1 not null comment '是否有效:0-无效,1-有效',
  CREATE_USER varchar(200) null comment '创建人',
  CREATE_TIME datetime   null comment '创建时间',
  UPDATE_USER varchar(200) null comment '修改人',
  UPDATE_TIME datetime   null comment '修改时间'
) comment '网关路由参数表' charset = utf8;

create index idx_route_id on gateway_route_param_t (ROUTE_ID);

接口设计 接口定义

路由表配置接口

封装 gateway_route_t dao 层接口.

/**
 * <功能描述> 路由表接口
 *
 * @author 20024322
 * @date 2020/12/24 13:20
 */
public interface IRouteConfigService extends IService<RouteDomain>

路由参数表配置接口

封装 gateway_route_param_t dao 层接口.

/**
 * <功能描述> 路由参数表接口
 *
 * @author 20024322
 * @date 2020/12/24 13:20
 */
public interface IRouteParamConfigService extends IService<RouteParamDomain>

数据库路由服务接口

封装 路由表配置服务接口以及路由参数表配置接口, 对外层提供对数据库路由信息的操作.

/**
 * <功能描述> 数据库路由服务
 *
 * @author 20024322
 * @date 2020/12/24 13:20
 */
public interface IRoutePropertiesService

网关路由缓存接口

封装 RouteDefinitionRepository 接口,对外提供对网关路由缓存的刷新.

/**
 * <功能描述> 网关缓存路由服务
 *
 * @author 20024322
 * @date 2020/12/24 13:20
 */
public interface IGatewayRouteService extends ApplicationEventPublisherAware

路由事件监听接口

配置需要监听路由变化的 service 实现

/**
 * <功能描述> 路由事件监听接口
 *
 * @author 20024322
 * @date 2020/12/24 13:20
 */
public interface RouteEventListener extends ApplicationListener<RefreshCacheEvent>

数据库黑白名单配置接口

/**
 * <功能描述> API Filter 接口定义
 *
 * @author 20024322
 * @date 2020/12/24 13:20
 */
public interface IApiFilterService

网关白名单缓存接口

提供指定路由 API 白名单check 监听路由事件

/**
 * <功能描述> API 白名单缓存接口
 *
 * @author 20024322
 * @date 2020/12/24 13:20
 */
public interface IApiCacheService extends RouteEventListener

路由参数执行校验接口

封装 提供路由参数的校验的接口.

/**
 * <功能描述> 路由参数校验
 *
 * @author 20024322
 * @date 2020/12/24 13:20
 */
public interface IRouteValidateExecutorService

接口类图 路由及黑白名单类图

断言及过滤器封装类图

集群缓存刷新事件处理策略类图

路由初始化设计 重载 PropertiesRouteDefinitionLocator

/**
 * <功能描述> 重写 PropertiesRouteDefinitionLocator bean
 * 将配置文件中的路由信息通过 MysqlRouteConfig 载入。
 *
 * @author 20024322
 * @date 2020/12/24 13:20
 */
@Configuration
@AutoConfigureBefore({MysqlRouteConfig.class})
public class PropertiesRouteConfig {
  @Bean
  public PropertiesRouteDefinitionLocator propertiesRouteDefinitionLocator(
      GatewayProperties properties) {
    return new PropertiesRouteDefinitionLocator(new GatewayProperties());
  }
}

定义 initMysqlRouteDefinition Bean 加载数据库及配置文件的路由配置

/**
 * <功能描述> 从Mysql中初始化路由信息
 * 覆盖配置文件中的路由信息
 *
 * @author 20024322
 * @date 2020/12/24 13:20
 */
@Configuration
public class MysqlRouteConfig {
  private final IRoutePropertiesService routePropertiesService;
  private final IGatewayRouteService gatewayRouteService;

  public MysqlRouteConfig(IRoutePropertiesService routePropertiesService, IGatewayRouteService gatewayRouteService) {
    this.routePropertiesService = routePropertiesService;
    this.gatewayRouteService = gatewayRouteService;
  }

  /**
   * 初始化 gatewayProperties 中的 route
   *
   * @param gatewayProperties
   * @return
   */
  @Bean
  public List<RouteDefinition> initMysqlRouteDefinition(GatewayProperties gatewayProperties) {
    List<RouteDefinition> gatewayPropertiesRoutes = gatewayProperties.getRoutes();

    //初始化数据库路由信息
    List<RouteDefinition> routeDefinitionList = routePropertiesService.getRouteDefinitionList();
    if (CollectionUtils.isEmpty(gatewayProperties.getRoutes()) && CollectionUtils.isEmpty(routeDefinitionList)) {
      throw new BizBaseException(HprmcExceptionCode.ROUTE_NOT_FOUND);
    }

    Set<String> routeIds = routeDefinitionList.stream()
        .map(RouteDefinition::getId).collect(Collectors.toSet());
    if (gatewayPropertiesRoutes.stream().anyMatch(r -> routeIds.contains(r.getId()))) {
      throw new BizBaseException(HprmcExceptionCode.ROUTE_INIT_CONFLICT);
    }

    //将配置文件中的路由信息添加到 InMemoryRouteDefinitionRepository 成员变量中
    if (!CollectionUtils.isEmpty(gatewayPropertiesRoutes)) {
      gatewayPropertiesRoutes.forEach(gatewayRouteService::addInMemoryRouteRefresh);
    }

    //写到 InMemoryRouteDefinitionRepository 成员初始化缓存
    if (!CollectionUtils.isEmpty(routeDefinitionList)) {
      routeDefinitionList.forEach(gatewayRouteService::addInMemoryRouteRefresh);
    }
    return routeDefinitionList;
  }
}

到此这篇关于SpringCloud Gateway 利用 Mysql 实现动态路由的方法的文章就介绍到这了,更多相关SpringCloud Gateway 实现动态路由内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • EasyExcel自定义导出列和顺序实例代码

    EasyExcel自定义导出列和顺序实例代码

    这篇文章主要给大家介绍了关于EasyExcel自定义导出列和顺序的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-07-07
  • 基于Spring实现零重启自由编排任务的定时管理器

    基于Spring实现零重启自由编排任务的定时管理器

    我们发现,我们使用Spring自带的定时任务如果要有修改,那么就要修改代码,然后重启项目,所以本文就带大家实现一个零重启自由编排任务的定时管理器吧
    2023-07-07
  • idea创建Spring项目的方法步骤(图文)

    idea创建Spring项目的方法步骤(图文)

    这篇文章主要介绍了idea创建Spring项目的方法步骤(图文),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-01-01
  • java 缓冲流的概念使用方法以及实例详解

    java 缓冲流的概念使用方法以及实例详解

    这篇文章主要为大家介绍了java 缓冲流的概念使用方法以及实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • 解决Mybatis-plus找不到对应表及默认表名命名规则的问题

    解决Mybatis-plus找不到对应表及默认表名命名规则的问题

    这篇文章主要介绍了解决Mybatis-plus找不到对应表及默认表名命名规则的问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-11-11
  • eclipse/IDEA配置javafx项目步骤(图文教程)

    eclipse/IDEA配置javafx项目步骤(图文教程)

    这篇文章主要介绍了eclipse/IDEA配置javafx项目步骤(图文教程),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-03-03
  • 实例讲解java定时任务

    实例讲解java定时任务

    这篇文章主要介绍了实例讲解java定时任务,感兴趣的的朋友可以参考下
    2015-08-08
  • Maven版本冲突的三种解决方法

    Maven版本冲突的三种解决方法

    在Maven项目中,依赖传递可能导致Jar包版本冲突,常见的解决策略包括依赖排除、版本锁定和使用maven-shade-plugin插件,本文就来介绍一下这三种解决方法,感兴趣的可以了解一下
    2024-10-10
  • Java中文乱码解决方案全解析,让你的程序“说人话”!

    Java中文乱码解决方案全解析,让你的程序“说人话”!

    探索Java中文乱码解决方案全解析,让你的程序终于能“说人话”!厌倦了看着一串串的问号或者奇怪符号吗?跟着我们的指南,一步步轻松解锁中文乱码的秘密,让你的代码清晰表达每一个字,需要的朋友可以参考下
    2024-02-02
  • Java对称加密工作模式原理详解

    Java对称加密工作模式原理详解

    这篇文章主要介绍了Java对称加密工作模式原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02

最新评论