spring-gateway 基于 nacos 配置文件的动态路由

简介: spring-gateway 基于 nacos 配置文件的动态路由

动态路由的实现方式多种多样,研究一下基于 nacos 配置文件形式的动态路由。


1. 创建项目,并pom.xml文件引入如下依赖

<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.olive</groupId>
 <artifactId>olive-gateway</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.7.1</version>
 </parent>
 <dependencyManagement>
  <dependencies>
   <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-dependencies</artifactId>
    <version>2021.0.3</version>
    <type>pom</type>
    <scope>import</scope>
   </dependency>
   <dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-dependencies</artifactId>
    <version>2021.1</version>
    <type>pom</type>
    <scope>import</scope>
   </dependency>
  </dependencies>
 </dependencyManagement>
 <dependencies>
  <dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-gateway</artifactId>
  </dependency>
  <dependency>
   <groupId>com.alibaba.cloud</groupId>
   <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  </dependency>
  <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>2.0.9</version>
  </dependency>
 </dependencies>
</project>

2. 增加一个配置类

主要配置 nacos 的 dataId 与 group

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "route.nacos")
public class GatewayConfig {
    private String dataId;
    private String group;
    private int timeout;
    //省略 getter  setter   
}


3.定义监听路由变化类

InFileRouteDefinitionRepository 类主要是简单 nacos 中的配置文件routes.json 的变化;只要监听到 routes.json 就进行路由更新。

import java.util.List;
import java.util.concurrent.Executor;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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 com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.olive.config.GatewayConfig;
import com.olive.route.model.GatewayRouteDO;
import reactor.core.publisher.Mono;
@Component
public class InFileRouteDefinitionRepository implements ApplicationEventPublisherAware{
    @Value("${spring.cloud.nacos.discovery.server-addr}")
    private String nacosServer;
    @Autowired
    private RouteDefinitionWriter routeDefinitionWriter;
    private ApplicationEventPublisher publisher;
    @Autowired
    private GatewayConfig gatewayConfig;
   @PostConstruct
   private void init() {
       dynamicRouteByListener(gatewayConfig.getDataId(), gatewayConfig.getGroup(), 
           nacosServer, gatewayConfig.getTimeout());
   }
    /**
     * 监听Nacos Server下发的动态路由配置
     */
    public void dynamicRouteByListener(String dataId, String group, String nacosServer, int timeout) {
        try {
            ConfigService configService = NacosFactory.createConfigService(nacosServer);
            String content = configService.getConfig(dataId, group, timeout);
            configService.addListener(dataId, group, new Listener() {
             @Override
                public void receiveConfigInfo(String configInfo) {
                    updateConfig(configInfo);
                }
                @Override
                public Executor getExecutor() {
                    return null;
                }
            });
            updateConfig(content);
        } catch (NacosException e) {
         e.printStackTrace();
        }
    }
    private void updateConfig(String configInfo) {
        try {
            GatewayRouteDO gatewayRouteDO = JSON.parseObject(configInfo, GatewayRouteDO.class);
            List<RouteDefinition> routeList = gatewayRouteDO.getRoutes();
            if (CollectionUtils.isNotEmpty(routeList)) {
                for (RouteDefinition routeDefinition : routeList) {
                    this.update(routeDefinition);
                }
            }
        } catch (Exception e) {
         e.printStackTrace();
        }
    }
    /**
     * 增加路由
     */
    public String add(RouteDefinition definition) {
        routeDefinitionWriter.save(Mono.just(definition)).subscribe();
        this.publisher.publishEvent(new RefreshRoutesEvent(this));
        return "success";
    }
    /**
     * 更新路由
     */
    public String update(RouteDefinition definition) {
        try {
            this.routeDefinitionWriter.delete(Mono.just(definition.getId()));
        } catch (Exception e) {
            return "update fail, not find route routeId: " + definition.getId();
        }
        try {
            routeDefinitionWriter.save(Mono.just(definition)).subscribe();
            this.publisher.publishEvent(new RefreshRoutesEvent(this));
            return "success";
        } catch (Exception e) {
         e.printStackTrace();
            return "update route fail";
        }
    }
    /**
     * 删除路由
     */
    public String delete(String id) {
        try {
            this.routeDefinitionWriter.delete(Mono.just(id));
            return "delete success";
        } catch (Exception e) {
            e.printStackTrace();
            return "delete route fail";
        }
    }
    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }
}

4. 增加 application.yml 配置文件

server:
  port: 8089
spring:
  application:
    name: olive-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.255.10:8848
route:
  nacos:
    dataId: routes.json
    group: DEFAULT_GROUP
    timeout: 1000

需要在配置中心 nacos 增加 routes.json 配置文件;这个 json 文件的格式一定要符合 spring-gateway 的 route 格式;否则无法转换。routes.json 内容如下:

{
  "routes": [
    {
      "filters": [],
      "id": "pay_route",
      "order": 0,
      "predicates": [
        {
          "args": {
            "pattern": "/pay/**"
          },
          "name": "Path"
        }
      ],
      "uri": "lb://pay-service"
    },
    {
      "filters": [
        {
          "name": "RewritePath",
          "args": {
            "regexp": "/user/(?<remaining>.*)",
            "replacement": "/${remaining}"
          }
        }
      ],
      "id": "user_route",
      "order": 0,
      "predicates": [
        {
          "args": {
            "pattern": "/user/**"
          },
          "name": "Path"
        }
      ],
      "uri": "lb://user-center-service"
    }
  ]
}

5. 创建springboot 引导类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@SpringBootApplication
public class GwApplication {
 public static void main(String[] args) {
   SpringApplication.run(GwApplication.class, args);
 }
}

测试验证只要通过在配置中心 nacos;修改 routes.json 配置文件即可。

相关文章
|
2月前
|
XML Java 数据格式
Spring从入门到入土(xml配置文件的基础使用方式)
本文详细介绍了Spring框架中XML配置文件的使用方法,包括读取配置文件、创建带参数的构造对象、使用工厂方法和静态方法创建对象、对象生命周期管理以及单例和多例模式的测试。
97 7
Spring从入门到入土(xml配置文件的基础使用方式)
|
2月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,包括版本兼容性、安全性、性能调优等方面。
162 1
|
29天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,创建并配置 Spring Boot 项目,实现后端 API;然后,使用 Ant Design Pro Vue 创建前端项目,配置动态路由和菜单。通过具体案例,展示了如何快速搭建高效、易维护的项目框架。
102 62
|
2月前
|
Java API Spring
在 Spring 配置文件中配置 Filter 的步骤
【10月更文挑战第21天】在 Spring 配置文件中配置 Filter 是实现请求过滤的重要手段。通过合理的配置,可以灵活地对请求进行处理,满足各种应用需求。还可以根据具体的项目要求和实际情况,进一步深入研究和优化 Filter 的配置,以提高应用的性能和安全性。
|
27天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,帮助开发者提高开发效率和应用的可维护性。
51 2
|
2月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用
【10月更文挑战第8天】本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,通过 Spring Initializr 创建并配置 Spring Boot 项目,实现后端 API 和安全配置。接着,使用 Ant Design Pro Vue 脚手架创建前端项目,配置动态路由和菜单,并创建相应的页面组件。最后,通过具体实践心得,分享了版本兼容性、安全性、性能调优等注意事项,帮助读者快速搭建高效且易维护的应用框架。
45 3
|
2月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用
【10月更文挑战第7天】本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,通过 Spring Initializr 创建 Spring Boot 项目并配置 Spring Security。接着,实现后端 API 以提供菜单数据。在前端部分,使用 Ant Design Pro Vue 脚手架创建项目,并配置动态路由和菜单。最后,启动前后端服务,实现高效、美观且功能强大的应用框架。
54 2
|
2月前
|
Java 测试技术 Spring
springboot学习三:Spring Boot 配置文件语法、静态工具类读取配置文件、静态工具类读取配置文件
这篇文章介绍了Spring Boot中配置文件的语法、如何读取配置文件以及如何通过静态工具类读取配置文件。
63 0
springboot学习三:Spring Boot 配置文件语法、静态工具类读取配置文件、静态工具类读取配置文件
|
3月前
|
存储 Java Nacos
学成在线笔记+踩坑(4)——【媒资管理模块】上传图片,Nacos+Gateway+MinIO
媒资管理模块简介、MinIO构建分布式文件系统、MinIO数据恢复演示 、【媒资模块】上传图片
学成在线笔记+踩坑(4)——【媒资管理模块】上传图片,Nacos+Gateway+MinIO
|
3月前
|
SpringCloudAlibaba JavaScript 前端开发
谷粒商城笔记+踩坑(2)——分布式组件、前端基础,nacos+feign+gateway+ES6+vue脚手架
分布式组件、nacos注册配置中心、openfegin远程调用、网关gateway、ES6脚本语言规范、vue、elementUI
谷粒商城笔记+踩坑(2)——分布式组件、前端基础,nacos+feign+gateway+ES6+vue脚手架