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配置文件的使用方法,包括读取配置文件、创建带参数的构造对象、使用工厂方法和静态方法创建对象、对象生命周期管理以及单例和多例模式的测试。
121 7
Spring从入门到入土(xml配置文件的基础使用方式)
|
2月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,包括版本兼容性、安全性、性能调优等方面。
178 1
|
1月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,创建并配置 Spring Boot 项目,实现后端 API;然后,使用 Ant Design Pro Vue 创建前端项目,配置动态路由和菜单。通过具体案例,展示了如何快速搭建高效、易维护的项目框架。
115 62
|
2月前
|
Java API Spring
在 Spring 配置文件中配置 Filter 的步骤
【10月更文挑战第21天】在 Spring 配置文件中配置 Filter 是实现请求过滤的重要手段。通过合理的配置,可以灵活地对请求进行处理,满足各种应用需求。还可以根据具体的项目要求和实际情况,进一步深入研究和优化 Filter 的配置,以提高应用的性能和安全性。
|
4月前
|
Cloud Native Java Nacos
微服务时代的新宠儿!Spring Cloud Nacos实战指南,带你玩转服务发现与配置管理,拥抱云原生潮流!
【8月更文挑战第29天】Spring Cloud Nacos作为微服务架构中的新兴之星,凭借其轻量、高效的特点,迅速成为服务发现、配置管理和治理的首选方案。Nacos(命名和配置服务)由阿里巴巴开源,为云原生应用提供了动态服务发现及配置管理等功能,简化了服务间的调用与依赖管理。本文将指导你通过五个步骤在Spring Boot项目中集成Nacos,实现服务注册、发现及配置动态管理,从而轻松搭建出高效的微服务环境。
304 0
|
1月前
|
存储 人工智能 Java
Spring AI Alibaba 配置管理,用 Nacos 就够了
本文通过一些实操案例展示了 Spring AI Alibaba + Nacos 在解决 AI 应用中一系列复杂配置管理挑战的方案,从动态 Prompt 模板的灵活调整、模型参数的即时优化,到敏感信息的安全加密存储。Spring AI Alibaba 简化了对接阿里云通义大模型的流程,内置 Nacos 集成也为开发者提供了无缝衔接云端配置托管的捷径,整体上极大提升了 AI 应用开发的灵活性和响应速度。
217 13
|
1月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,帮助开发者提高开发效率和应用的可维护性。
81 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 脚手架创建前端项目,配置动态路由和菜单,并创建相应的页面组件。最后,通过具体实践心得,分享了版本兼容性、安全性、性能调优等注意事项,帮助读者快速搭建高效且易维护的应用框架。
61 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 脚手架创建项目,并配置动态路由和菜单。最后,启动前后端服务,实现高效、美观且功能强大的应用框架。
64 2
|
2月前
|
Java 测试技术 Spring
springboot学习三:Spring Boot 配置文件语法、静态工具类读取配置文件、静态工具类读取配置文件
这篇文章介绍了Spring Boot中配置文件的语法、如何读取配置文件以及如何通过静态工具类读取配置文件。
157 0
springboot学习三:Spring Boot 配置文件语法、静态工具类读取配置文件、静态工具类读取配置文件