抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

Spring Cloud Gateway动态路由实现

在实现动态路由之前,你至少能搭建一个简单的Gateway项目,并对其有一定的了解,具体可以参考Spring Cloud Gateway 入门学习

本文要实现的动态路由为在数据库中存储路由配置,并提供一个页面可以配置路由。

准备工作

数据库脚本(以下脚本针对PostgreSQL数据库,脚本源文件地址):

-- 创建模式
create schema db_base;
-- 创建表
create table db_base.t_route(
    c_id varchar(300) primary key not null,
    c_name varchar(300) not null,
    c_predicates varchar(1200),
    c_url varchar(900) not null,
    c_filters varchar(1200)
);
-- 初始化一条测试数据
INSERT INTO "db_base"."t_route"("c_id", "c_name", "c_predicates", "c_url", "c_filters") VALUES ('scs-blog', '我的博客', '["Path=/blog/**"]', 'https://jiangliuhong.top/', '["RewritePath=/blog(?<segment>/?.*), $\\{segment}"]');

Gateway中追加以下依赖:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<dependency>
  <groupId>org.postgresql</groupId>
  <artifactId>postgresql</artifactId>
</dependency>

修改application.yml文件:

spring:
  datasource:
    url: jdbc:postgresql://127.0.0.1:5432/scs
    username: sa
    password: 6789@jkl
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: org.postgresql.Driver
    druid:
      initial-size: 5
      min-idle: 5
      max-active: 20
      validation-query: select version()
  jpa:
    database: postgresql
    show-sql: true
    properties:
      hibernate:
        hbm2ddl:
          # 配置开启自动更新表结构
          auto: update

核心方法

Gateway源码地址:https://github.com/jiangliuhong/springcloud-stu/tree/master/scs-gateway

RouteService

原文件地址:https://github.com/jiangliuhong/springcloud-stu/blob/master/scs-gateway/src/main/java/top/jiangliuhong/scs/gateway/service/RouteService.java

@Service
public class RouteService {

    private static final Logger logger = LoggerFactory.getLogger(RouteService.class);

    @Resource
    private RouteRepository routeRepository;

    @Autowired
    private RouteDefinitionWriter routeDefinitionWriter;

    /**
     * 加载配置
     */
    public void loadRoute() {
        // getRoutes 从数据库加载数据
        List<Route> routes = getRoutes();
        if (CollectionUtils.isEmpty(routes)) {
            logger.warn("当前没有路由需要加载");
            return;
        }
        for (Route route : routes) {
            RouteDefinition definition = new RouteDefinition();
            definition.setId(route.getId());
            try {
                definition.setUri(new URI(route.getUrl()));
            } catch (URISyntaxException e) {
                logger.error("初始化uri失败:" + route.getUrl(), e);
                continue;
            }
            if (StringUtils.isBlank(route.getPredicates())) {
                logger.warn("{}[{}]的Predicates为空", route.getId(), route.getName());
                continue;
            }
            // 路由设置
            List<PredicateDefinition> predicates = Lists.newArrayList();
            List<String> predicatesList = JSON.parseArray(route.getPredicates(), String.class);
            for (String p : predicatesList) {
                predicates.add(new PredicateDefinition(p));
            }
            definition.setPredicates(predicates);
            // 过滤器设置
            if (StringUtils.isNotBlank(route.getFilters())) {
                List<FilterDefinition> filters = Lists.newArrayList();
                List<String> filtersList = JSON.parseArray(route.getFilters(), String.class);
                for (String f : filtersList) {
                    filters.add(new FilterDefinition(f));
                }
                definition.setFilters(filters);
            }
              // 保存路由信息
            routeDefinitionWriter.save(Mono.just(definition)).subscribe();
        }
        // 刷新路由
        ApplicationEventUtils.pushEvent(new RefreshRoutesEvent(this));
    }
}

RouteRunner

启动时加载数据库路由

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class RouteRunner implements CommandLineRunner {
    @Autowired
    private RouteService routeService;

    @Override
    public void run(String... args) throws Exception {
        routeService.loadRoute();
    }
}

前端页面

前端源码:https://github.com/jiangliuhong/springcloud-stu/tree/master/scs-websource/scsweb-gateway

评论