Spring Cloud Gateway:使用RestController动态更新路由
相关类介绍
动态路由(自己控制,非注册中心控制)涉及两个很重要的Bean:
- RouteDefinitionWriter:用于添加、修改、删除路由规则。
- RouteDefinitionLocator:用于查询路由规则。
以及一个相关事件:
- RefreshRoutesEvent:用于更新路由规则,使上述的操作生效。
依赖及配置
先引入相关依赖:
<?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"><modelVersion>4.0.0</modelVersion><groupId>com.chilun</groupId><artifactId>API_OPEN_SPACE_GATEWAY</artifactId><version>1.0-SNAPSHOT</version><properties><java.version>17</java.version><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>2.7.9</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>2021.0.5</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>2021.0.5.0</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-config</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId><version>2021.0.5.0</version></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bootstrap</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId><version>3.0.3</version></dependency></dependencies>
</project>
以及配置文件application.yml:
server:port: 8002
logging:level:org.springframework.cloud.gateway: DEBUG
myGateway:RoutePrefix: api
spring:profiles:active: devmvc:pathmatch:matching-strategy: ant_path_matchercloud:gateway:enabled: true
服务中心相关配置:
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.application.name=gateway
核心代码
定义服务层接口:
import com.chilun.apiopenspace.gateway.entity.dto.DeleteRouteRequest;
import com.chilun.apiopenspace.gateway.entity.dto.InitRouteRequest;
import com.chilun.apiopenspace.gateway.entity.dto.SaveOrUpdateRouteRequest;
import com.chilun.apiopenspace.gateway.entity.pojo.RoutePOJO;
import reactor.core.publisher.Mono;import java.util.List;/*** @author 齿轮* @date 2024-02-08-22:39*/
public interface RouteService {void init(InitRouteRequest request);void saveOrUpdate(SaveOrUpdateRouteRequest request);void delete(DeleteRouteRequest request);void refresh();Mono<List<RoutePOJO>> getAll();
}
实现类(适配器模式):
package com.chilun.apiopenspace.gateway.service.impl;import com.chilun.apiopenspace.gateway.entity.dto.DeleteRouteRequest;
import com.chilun.apiopenspace.gateway.entity.dto.InitRouteRequest;
import com.chilun.apiopenspace.gateway.entity.dto.SaveOrUpdateRouteRequest;
import com.chilun.apiopenspace.gateway.entity.pojo.RoutePOJO;
import com.chilun.apiopenspace.gateway.service.RouteService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionLocator;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.net.URI;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;/*** @author 齿轮* @date 2024-02-08-22:43*/
@Service
public class RouteServiceAdepter implements RouteService, ApplicationEventPublisherAware {@Resourceprivate RouteDefinitionWriter routeDefinitionWriter;@Resourceprivate RouteDefinitionLocator locator;@Value("${myGateway.RoutePrefix}")private String routePrefix;// @PostConstruct
// public void test(){
// SaveOrUpdateRouteRequest saveOrUpdateRouteRequest = new SaveOrUpdateRouteRequest();
// saveOrUpdateRouteRequest.setUri("https://www.baidu.com");
// saveOrUpdateRouteRequest.setId("1");
// saveOrUpdate(saveOrUpdateRouteRequest);
// }@Overridepublic void init(InitRouteRequest request) {request.getList().forEach(this::saveOrUpdate);this.publisher.publishEvent(new RefreshRoutesEvent(this));}@Overridepublic void saveOrUpdate(SaveOrUpdateRouteRequest request) {RouteDefinition routeDefinition = new RouteDefinition();routeDefinition.setId(request.getId());routeDefinition.setUri(URI.create(request.getUri()));String Path = "/" + routePrefix + "/" + request.getId();routeDefinition.setPredicates(Collections.singletonList(new PredicateDefinition("Path=" + Path)));routeDefinition.setFilters(Collections.singletonList(new FilterDefinition("SetPath=/")));routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();}@Overridepublic void delete(DeleteRouteRequest request) {routeDefinitionWriter.delete(Mono.just(request.getId())).subscribe();this.publisher.publishEvent(new RefreshRoutesEvent(this));}@Overridepublic void refresh() {this.publisher.publishEvent(new RefreshRoutesEvent(this));}@Overridepublic Mono<List<RoutePOJO>> getAll() {return locator.getRouteDefinitions().map(routeDefinition -> {RoutePOJO routePOJO = new RoutePOJO();routePOJO.setId(routeDefinition.getId());routePOJO.setURI(routeDefinition.getUri().toString());routePOJO.setPredicates(routeDefinition.getPredicates().stream().map(predicate -> predicate.getArgs().values().toString()).collect(Collectors.toList()));routePOJO.setFilters(routeDefinition.getFilters().stream().map(FilterDefinition::getName).collect(Collectors.toList()));return routePOJO;}).collectList();}private ApplicationEventPublisher publisher;@Overridepublic void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {this.publisher = applicationEventPublisher;}
}
Controller层代码:
package com.chilun.apiopenspace.gateway.controller;import com.chilun.apiopenspace.gateway.entity.dto.DeleteRouteRequest;
import com.chilun.apiopenspace.gateway.entity.dto.InitRouteRequest;
import com.chilun.apiopenspace.gateway.entity.dto.SaveOrUpdateRouteRequest;
import com.chilun.apiopenspace.gateway.entity.pojo.RoutePOJO;
import com.chilun.apiopenspace.gateway.service.RouteService;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;import javax.annotation.Resource;
import java.util.List;/*** @author 齿轮* @date 2024-02-13-22:13*/
@RestController
@RequestMapping("/manage")
public class RouteController {@ResourceRouteService service;@PostMapping("/update")public void add(@RequestBody SaveOrUpdateRouteRequest request) {service.saveOrUpdate(request);}@PostMapping("/init")public void init(@RequestBody InitRouteRequest request) {service.init(request);}@PostMapping("/delete")public void delete(@RequestBody DeleteRouteRequest request) {service.delete(request);}@GetMapping("/getAll")public Mono<List<RoutePOJO>> getAll() {return service.getAll();}@GetMapping("/refresh")public void refresh(){service.refresh();}
}
代码请自行查看,看不懂就问大语言模型。
代码逻辑较简单,仅基本增删改查功能,其他延伸方面如安全等请自行探索。
其他代码
实体类:
package com.chilun.apiopenspace.gateway.entity.dto;import lombok.Data;/*** @author 齿轮* @date 2024-02-13-20:01*/
@Data
public class DeleteRouteRequest {String id;
}package com.chilun.apiopenspace.gateway.entity.dto;import lombok.Data;import java.util.List;/*** @author 齿轮* @date 2024-02-13-20:00*/
@Data
public class InitRouteRequest {List<SaveOrUpdateRouteRequest> list;
}package com.chilun.apiopenspace.gateway.entity.dto;import lombok.Data;/*** @author 齿轮* @date 2024-02-13-19:55*/
@Data
public class SaveOrUpdateRouteRequest {String id;String uri;
}package com.chilun.apiopenspace.gateway.entity.pojo;import lombok.Data;import java.util.List;/**** Route实体类,用于远程调用接受参数* @author 齿轮* @date 2024-02-13-19:53*/
@Data
public class RoutePOJO {String id;String URI;List<String> Predicates;List<String> Filters;
}
swagger文档配置类:
package com.chilun.apiopenspace.gateway.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;/*** @author 齿轮* @date 2024-02-14-1:32*/
@Configuration
@EnableSwagger2
@Profile({"dev"})
public class Knife4jConfig {@Beanpublic Docket defaultApi2() {return new Docket(DocumentationType.SWAGGER_2).apiInfo(new ApiInfoBuilder().title("API开放平台接口文件").description("API开放平台").contact(new Contact("chilun", "http://home.shoumingchilun.cn", "2265501251@qq.com")).version("1.0").build()).select()// 指定 Controller 扫描包路径.apis(RequestHandlerSelectors.basePackage("com.chilun.apiopenspace.gateway.controller")).paths(PathSelectors.any()).build();}
}
相关文章:
Spring Cloud Gateway:使用RestController动态更新路由
相关类介绍 动态路由(自己控制,非注册中心控制)涉及两个很重要的Bean: RouteDefinitionWriter:用于添加、修改、删除路由规则。RouteDefinitionLocator:用于查询路由规则。 以及一个相关事件:…...

用Python动态展示排序算法
文章目录 选择冒泡插入排序归并排序希尔排序 经常看到这种算法可视化的图片,但往往做不到和画图的人心灵相通,所以想自己画一下,本文主要实现归并排序和希尔排序,如果想实现其他算法可参考这篇 C语言实现各种排序算法[选择&#x…...
vscode代码快捷键
1、 log console.log()2、edf export default (first)>{ second } 或者 export default function(params)>{ }可以使用tab键切换修改项 3、ednf export default function first(second) {third}4、! 生成html模板 5、div#app <div id"app"></di…...
深入了解C++:形参、内联、重载、引用、const和指针、new和delete
形参带默认值的函数 1.给默认值的时候从右向左给。 2.定义出可以给形参默认值,声明也可以给形参默认值。 3.形参默认值只能出现一次。 4.参数调用的效率问题 #sum(10,20)对应了五条汇编指令 mov eax,dword ptr[ebp-8] push eax mov ecx dword ptr[ebp-4] push …...
Linux 目录结构结构
Linux 目录结构结构 概念 Linux 没有 C、D、E...盘符,只有一个目录树。通过挂载,将不同的磁盘挂载到目录树下,通过目录访问磁盘。 不同目录的作用 目录存放内容/作用/根目录,目录树的起点,存放所有文件。…...

C++基础入门:掌握核心概念(超全!)
C作为一门广泛使用的编程语言,以其高性能和灵活性在软件开发领域占据重要地位。无论是游戏开发、系统编程还是实时应用,C都是一个不可或缺的工具。本博客旨在为初学者提供C编程语言的核心概念,帮助你建立坚实的基础。 C关键字 C关键字是编程…...

Linux第47步_安装支持linux的第三方库和mkimage工具
安装支持linux的第三方库和mkimage工具,做好移植前的准备工作。 编译linux内核之前,需要先在 ubuntu上安装“lzop库”和“libssl-dev库”,否则内核编译会失败。 mkimage工具会在zImage镜像文件的前面添加0x40个字节的头部信息,就可以得到uI…...

数据工程工程师学习路线图
数据工程岗位要求 Skill Sets required: - Hands on experience enabling data via Adobe Analytics and/or Google Analytics - Understanding of how customer level data is captured and stitched with behavioural data - Experience working with Testing (QA) and D…...

MySQL主从同步与分库分表
分库分表...

百度PaddleOCR字符识别推理部署(C++)
1 环境 1.opencv(https://sourceforge.net/projects/opencvlibrary/) 2.cmake(https://cmake.org/download/) 3.vs2019((https://github.com/PaddlePaddle/PaddleOCR/tree/release/2.1) 4.paddleOCR项目-建议2.0(http…...

C++ Qt框架开发 | 基于Qt框架开发实时成绩显示排序系统(2)折线图显示
对上一篇的工作C学习笔记 | 基于Qt框架开发实时成绩显示排序系统1-CSDN博客继续优化,增加一个显示运动员每组成绩的折线图。 1)在Qt Creator的项目文件(.pro文件)中添加对Qt Charts模块的支持: QT charts 2…...

Microsoft Excel 加载数据分析工具
Microsoft Excel 加载数据分析工具 1. 打开 Excel,文件 -> 选项2. 加载项 -> 转到…3. 分析工具库、分析工具库 - VBA4. 打开 Excel,数据 -> 数据分析References 1. 打开 Excel,文件 -> 选项 2. 加载项 -> 转到… 3…...
Day32 贪心算法part02
买卖股票的最佳时机 太牛了我,随随便便双指针秒杀 md题解里面双指针都没用直接for循环秒杀 跳跃游戏 写成这样纯粹是没有看到第一次跳跃必须从第一个开始 class Solution:def canJump(self, nums: List[int]) -> bool:if len(nums) 1:return Truefor i in …...
3分钟带你了解Vue3的nextTick()
前言 Vue 实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新。简单来说,Vue在修改数据后,视图不会立刻更新,而是等同一事件循环中的所有数据变化完成之后,再统一进行视图更新ÿ…...
数据库的使用方法
sqlite3 API: 头文件: #include <sqlite3.h> 编译时候要加上-lsqlite3 gcc a.c -lsqlite3 1)sqlite3_open int sqlite3_open(const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb /* OUT: SQLite db …...

HTML5和CSS3强化知识总结
HTML5的新特性 HTML5的新增特性主要是针对于以前的不足,增一些新的标签、新的表单和新的表单属性等。这些新特性都有兼容性问题,基本是IE9以上版本的浏览器才支持,如果不考虑兼容性问题,可以大量使用这些新特性。 HTML5新增的语义…...

华为机考入门python3--(13)牛客13-句子逆序
分类:列表 知识点: 列表逆序(和字符串逆序是一样的) my_list[::-1] 题目来自【牛客】 def reverse_sentence(sentence): # 将输入的句子分割words sentence.split() # 将单词逆序排列 words words[::-1] # 将单词用空…...
javaScript实现客户端直连AWS S3(亚马逊云)文件上传、断点续传、断网重传
写在前面:在做这个调研时我遇到的需求是前端直接对接亚马逊平台实现文件上传功能。上传视频文件通常十几个G、客户工作环境网络较差KB/s,且保证上传是稳定的,支持网络异常断点重试、文件断开支持二次拖入自动重传等。综合考虑使用的Aws S3的分…...

从基建发力,CESS 如何推动 RWA 发展?
2023 年 11 月 30 日,Web3 基金会(Web3 Foundation)宣布通过 Centrifuge 将部分资金投资于 RWA(Real World Assets,真实世界资产),试点投资为 100 万美元。Web3 基金会旨在通过支持专注于隐私、…...

qml写一个自适应登录框
1、前言 写一个可自由伸缩的登录框,,(横向上) 关键:给相关控件赋予 Layout.fillWidth: true 属性 即可。 2、代码 //main.qml import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQml 2.12 import QtQuic…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...

python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...