GateWay使用手册

好的,下面是优化后的版本。为了提高可读性和规范性,我对内容进行了结构化、简化了部分代码,同时增加了注释说明,便于理解。


1. 引入依赖

pom.xml 中添加以下依赖:

<dependencies><!-- Spring Cloud Gateway:提供API网关功能 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!-- Spring Cloud Alibaba Nacos Discovery:用于服务发现 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!-- Spring Cloud Loadbalancer:提供客户端负载均衡 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency>
</dependencies>

2. 启动类 (GateApplication.java)

定义主启动类,启动 Spring Boot 应用:

@SpringBootApplication  // 标明这是Spring Boot应用的入口
public class GateApplication {public static void main(String[] args) {SpringApplication.run(GateApplication.class, args);  // 启动应用}
}

3. 配置文件 (application.yml)

配置网关的基本设置、Nacos 服务发现以及路由规则。

server:port: 8080  # 配置网关监听的端口spring:application:name: gateway  # 应用名称,用于 Nacos 等服务发现cloud:nacos:discovery:server-addr: xiaotianlong.xyz:8848  # 配置 Nacos 服务器地址gateway:routes:  # 配置网关的路由规则# 路由规则 1- id: service_name  # 路由的唯一IDuri: lb://service_name  # 使用负载均衡访问注册到 Nacos 中的服务predicates:- Path=/user/**  # 请求路径以 `/user/` 开头时触发此路由filters:- AddRequestHeader=X-Request-Foo, Bar  # 添加请求头# 路由规则 2- id: service_name2uri: lb://service_name2predicates:- Path=/order/**  # 请求路径以 `/order/` 开头时触发此路由

4. 自定义全局过滤器

定义一个全局过滤器,记录请求的时间并打印日志。

@Component  // 声明为Spring组件
public class MyGlobalFilter implements GlobalFilter, Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 记录请求开始时间System.out.println("请求开始时间: " + System.currentTimeMillis());// 放行请求return chain.filter(exchange).then(Mono.fromRunnable(() -> {// 记录请求结束时间System.out.println("请求结束时间: " + System.currentTimeMillis());}));}@Overridepublic int getOrder() {// 过滤器的执行顺序,数字越小优先级越高return 0;}
}

5. 自定义Gateway过滤器

创建一个自定义的 Gateway 过滤器工厂,允许动态配置过滤器的参数。

@Component
public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory<MyGatewayFilterFactory.Config> {// 内部配置类,允许用户配置过滤器的参数@Datapublic static class Config {private String pattern = "yyyy-MM-dd";  // 设置默认日期格式private String message = "默认日志信息";  // 自定义日志信息}public MyGatewayFilterFactory() {super(Config.class);  // 指定配置类类型}@Overridepublic List<String> shortcutFieldOrder() {return List.of("pattern", "message");  // 设置快捷字段顺序}@Overridepublic GatewayFilter apply(Config config) {// 创建过滤器逻辑return new OrderedGatewayFilter((exchange, chain) -> {DateTimeFormatter formatter = DateTimeFormatter.ofPattern(config.getPattern());System.out.println("请求开始时间: " + formatter.format(LocalDateTime.now()));System.out.println(config.getMessage());  // 打印自定义日志信息return chain.filter(exchange).then(Mono.fromRunnable(() -> {System.out.println("请求结束时间: " + formatter.format(LocalDateTime.now()));}));}, 1);//在这里设置顺序}
}

6. 配置自定义过滤器

application.yml 文件中配置自定义的 MyGatewayFilterFactory 过滤器,使其生效:

spring:cloud:gateway:routes:- id: example_routeuri: lb://some-servicepredicates:- Path=/somepath/**  # 路径匹配条件filters:- name: My  # 使用自定义过滤器args:pattern: "yyyy-MM-dd~HH:mm:ss"  # 自定义日期格式message: "这是一个统计时间的gateway过滤器"  # 自定义日志信息

或者

spring:cloud:gateway:routes:- id: example_routeuri: lb://some-servicepredicates:- Path=/somepath/**  # 路径匹配条件filters:# 由于设置了shortcutfieldorder,所以可以这样写- My="yyyy-MM-dd~HH:mm:ss", "这是一个统计时间的gateway过滤器"

案例1:登录检验

@Component
@EnableConfigurationProperties(AuthProperties.class)
public class AuthGlobalFilter implements GlobalFilter, Ordered {@Resourceprivate AuthProperties authProperties;@Resourceprivate JwtTool jwtTool;private final AntPathMatcher antPathMatcher = new AntPathMatcher();@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//1.获取requestServerHttpRequest request = exchange.getRequest();//2.判断路径是否需做登录拦截List<String> excludePaths = authProperties.getExcludePaths();if (isExclude(request.getPath())) {//此时不需要拦截,直接放行return chain.filter(exchange);}//3.获得tokenString token = request.getHeaders().getFirst("authorization");//4.检验并解析tokenLong userId = null;try {userId = jwtTool.parseToken(token);} catch (Exception e) {//设置响应状态码为401ServerHttpResponse response = exchange.getResponse();response.setStatusCode(HttpStatus.UNAUTHORIZED);//拦截return response.setComplete();}//todo 5.传递用户信息//6.放行return chain.filter(exchange);}private boolean isExclude(RequestPath path) {List<String> excludePaths = authProperties.getExcludePaths();for (String pattern : excludePaths) {if (antPathMatcher.match(pattern, path.toString())) {return true;}}return false;}@Overridepublic int getOrder() {return 0;}
}

7.结合Nacos实现动态路由

在Spring Cloud Gateway中,路由的配置默认是在项目启动时通过 org.springframework.cloud.gateway.route.CompositeRouteDefinitionLocator 进行加载的。这些配置一旦加载到内存中(通常是通过一个 Map 缓存),就不会随路由变化而更新,也不支持热更新功能。因此,我们需要借助 Nacos 来实现动态的路由更新功能。

这涉及到两个关键问题:

  • 如何监听Nacos配置变更?
  • 如何把新的路由信息更新到路由表中?

7.1 引入依赖

首先,我们需要在项目中引入Nacos的配置和启动依赖:

<!-- 统一配置管理 -->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency><!-- 加载bootstrap配置 -->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>

7.2 配置bootstrap.yaml

在网关项目的 resources 目录下,创建 bootstrap.yaml 文件,配置Nacos的服务地址和路由配置的相关信息:

spring:application:name: gatewaycloud:nacos:discovery:server-addr: xiaotianlong.xyz:8848config:server-addr: xiaotianlong.xyz:8848

7.3 定义配置监听器

接下来,我们编写一个配置监听器类,用于监听Nacos配置变更并更新路由。监听器需要通过 NacosConfigManager 获取配置内容,并在路由配置更新时,动态更新路由表。

package com.hmall.gateway.route;import cn.hutool.json.JSONUtil;
import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import com.hmall.common.utils.CollUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;import javax.annotation.PostConstruct;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executor;@Slf4j
@Component
@RequiredArgsConstructor
public class DynamicRouteLoader {private final RouteDefinitionWriter writer;private final NacosConfigManager nacosConfigManager;// 路由配置文件的dataId和groupprivate final String dataId = "gateway-routes.json";private final String group = "DEFAULT_GROUP";// 保存已更新的路由IDprivate final Set<String> routeIds = new HashSet<>();@PostConstructpublic void initRouteConfigListener() throws NacosException {// 注册Nacos配置监听器并拉取配置String configInfo = nacosConfigManager.getConfigService().getConfigAndSignListener(dataId, group, 5000, new Listener() {@Overridepublic Executor getExecutor() {return null;  // 默认执行器为null}@Overridepublic void receiveConfigInfo(String configInfo) {updateConfigInfo(configInfo);  // 配置变更时更新路由}});// 首次启动时加载配置updateConfigInfo(configInfo);}private void updateConfigInfo(String configInfo) {log.debug("监听到路由配置变更:{}", configInfo);// 1. 反序列化配置List<RouteDefinition> routeDefinitions = JSONUtil.toList(configInfo, RouteDefinition.class);// 2. 清除旧路由配置routeIds.forEach(routeId -> writer.delete(Mono.just(routeId)).subscribe());routeIds.clear();// 3. 判断并更新新的路由配置if (CollUtils.isEmpty(routeDefinitions)) {// 如果没有新的路由配置,直接结束return;}// 4. 更新新的路由配置routeDefinitions.forEach(routeDefinition -> {// 保存新路由writer.save(Mono.just(routeDefinition)).subscribe();// 记录路由ID,方便未来删除routeIds.add(routeDefinition.getId());});}
}

在Nacos控制台,我们可以添加路由配置文件 gateway-routes.json,类型选择JSON。路由配置的示例内容如下:
在这里插入图片描述

[{"id": "item","predicates": [{"name": "Path","args": {"_genkey_0":"/items/**", "_genkey_1":"/search/**"}}],"filters": [],"uri": "lb://item-service"},{"id": "cart","predicates": [{"name": "Path","args": {"_genkey_0":"/carts/**"}}],"filters": [],"uri": "lb://cart-service"},{"id": "user","predicates": [{"name": "Path","args": {"_genkey_0":"/users/**", "_genkey_1":"/addresses/**"}}],"filters": [],"uri": "lb://user-service"},{"id": "trade","predicates": [{"name": "Path","args": {"_genkey_0":"/orders/**"}}],"filters": [],"uri": "lb://trade-service"},{"id": "pay","predicates": [{"name": "Path","args": {"_genkey_0":"/pay-orders/**"}}],"filters": [],"uri": "lb://pay-service"}
]

通过以上配置,网关将能够动态地加载和更新路由配置,使得路由在Nacos配置变更时自动同步更新。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/483136.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot+Flowable快速实现工流_动态选择审批人员

前言 OA系统中的工作流不仅是企业日常运营的重要组成部分&#xff0c;也是实现企业数字化转型、提高工作效率和执行力的重要工具。 在国内大部分的工作流系统使用Activiti框架实现。 其实flowable也可以轻松实现工作流业务。在线体验JeecgFlow flowable简介 Flowable是一个使用…

【ONE·基础算法 || 动态规划(三)】

总言 主要内容&#xff1a;编程题举例&#xff0c;熟悉理解动态规划类题型&#xff08;回文串问题、两个数组的 dp问题&#xff09;。                文章目录 总言7、回文串问题7.1、 回文子串&#xff08;medium&#xff09;7.1.1、题解 7.2、 最长回文子串&#…

Python 3 教程第33篇(MySQL - mysql-connector 驱动)

Python MySQL - mysql-connector 驱动 MySQL 是最流行的关系型数据库管理系统&#xff0c;如果你不熟悉 MySQL&#xff0c;可以阅读我们的 MySQL 教程。 本章节我们为大家介绍使用 mysql-connector 来连接使用 MySQL&#xff0c; mysql-connector 是 MySQL 官方提供的驱动器。…

LLM*:路径规划的大型语言模型增强增量启发式搜索

路径规划是机器人技术和自主导航中的一个基本科学问题&#xff0c;需要从起点到目的地推导出有效的路线&#xff0c;同时避开障碍物。A* 及其变体等传统算法能够确保路径有效性&#xff0c;但随着状态空间的增长&#xff0c;计算和内存效率会严重降低。相反&#xff0c;大型语言…

【Db First】.NET开源 ORM 框架 SqlSugar 系列

.NET开源 ORM 框架 SqlSugar 系列 【开篇】.NET开源 ORM 框架 SqlSugar 系列【入门必看】.NET开源 ORM 框架 SqlSugar 系列【实体配置】.NET开源 ORM 框架 SqlSugar 系列【Db First】.NET开源 ORM 框架 SqlSugar 系列【Code First】.NET开源 ORM 框架 SqlSugar 系列【数据事务…

企业品牌曝光的新策略:短视频矩阵系统

企业品牌曝光的新策略&#xff1a;短视频矩阵系统 在当今数字化时代&#xff0c;短视频已经渗透到我们的日常生活之中&#xff0c;成为连接品牌与消费者的关键渠道。然而&#xff0c;随着平台于7月20日全面下线了短视频矩阵的官方接口&#xff0c;许多依赖于此接口的小公司和内…

006 MATLAB编程基础

01 M文件 MATLAB输入命令有两种方法&#xff1a; 一是在MATLAB主窗口逐行输入命令&#xff0c;每个命令之间用分号或逗号分隔&#xff0c;每行可包含多个命令。 二是将命令组织成一个命令语句文集&#xff0c;使用扩展名“.m”&#xff0c;称为M文件。它由一系列的命令和语句…

Java基于SpringBoot+Vue的IT技术交流和分享平台(附源码+lw+部署)

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

【计算机网络】实验3:集线器和交换器的区别及交换器的自学习算法

实验 3&#xff1a;集线器和交换器的区别及交换器的自学习算法 一、 实验目的 加深对集线器和交换器的区别的理解。 了解交换器的自学习算法。 二、 实验环境 • Cisco Packet Tracer 模拟器 三、 实验内容 1、熟悉集线器和交换器的区别 (1) 第一步&#xff1a;构建网络…

UICollectionView在xcode16编译闪退问题

使用xcode15运行工程&#xff0c;控制台会出现如下提示&#xff1a; Expected dequeued view to be returned to the collection view in preparation for display. When the collection views data source is asked to provide a view for a given index path, ensure that a …

Proteus8.17下载安装教程

Proteus是一款嵌入式系统仿真开发软件&#xff0c;实现了从原理图设计、单片机编程、系统仿真到PCB设计&#xff0c;真正实现了从概念到产品的完整设计&#xff0c;其处理器模型支持8051、HC11、PIC10/12/16/18/24/30/DsPIC33、AVR、ARM、8086和MSP430等&#xff0c;能够帮助用…

Vue教程|搭建vue项目|Vue-CLI2.x 模板脚手架

一、项目构建环境准备 在构建Vue项目之前&#xff0c;需要搭建Node环境以及Vue-CLI脚手架&#xff0c;由于本篇文章为上一篇文章的补充&#xff0c;也是为了给大家分享更为完整的搭建vue项目方式&#xff0c;所以环境准备部分采用Vue教程&#xff5c;搭建vue项目&#xff5c;V…

一款支持80+语言,包括:拉丁文、中文、阿拉伯文、梵文等开源OCR库

大家好&#xff0c;今天给大家分享一个基于PyTorch的OCR库EasyOCR&#xff0c;它允许开发者通过简单的API调用来读取图片中的文本&#xff0c;无需复杂的模型训练过程。 项目介绍 EasyOCR 是一个基于Python的开源项目&#xff0c;它提供了一个简单易用的光学字符识别&#xff…

cocotb pytest

打印python中的print &#xff0c; 应该使用 pytest -s

【C++】STL——map和set

目录 1、序列式容器和关联式容器前 2、set 2.1 set类的介绍 2.2 set的构造和迭代器 2.3 set的增删查 set 的插入 set的查找 set的删除 2.4 multiset和set的差异 3、map 3 .1 pair类型 3.2 map的构造 3.3 map的增删查 map的构造遍历 map的插入 map的删除 map的查…

java基础概念46-数据结构1

一、引入 List集合的三种实现类使用了不同的数据结构&#xff01; 二、数据结构的定义 三、常见的数据结构 3-1、栈 特点&#xff1a;先进后出&#xff0c;后进先出。 java内存容器&#xff1a; 3-2、队列 特点&#xff1a;先进先出、后进后出。 栈VS队列-小结 3-3、数组 3-…

Docker:在 ubuntu 系统上生成和加载 Docker 镜像

本文将介绍在 ubuntu系统上进行 Docker 镜像的生成和加载方法和代码。 文章目录 一、下载和安装 docker二、加载 docker 文件三、保存你的镜像四、将镜像上传到云端并通过连接下载和加载 Docker 镜像五、Docker 容器和本地的文件交互5.1 从容器复制文件到本地宿主机5.1.1 单个文…

《数据挖掘:概念、模型、方法与算法(第三版)》

嘿&#xff0c;数据挖掘的小伙伴们&#xff01;今天我要给你们介绍一本超级实用的书——《数据挖掘&#xff1a;概念、模型、方法与算法》第三版。这本书是数据挖掘领域的经典之作&#xff0c;由该领域的知名专家编写&#xff0c;系统性地介绍了在高维数据空间中分析和提取大量…

做异端中的异端 -- Emacs裸奔之路4: 你不需要IDE

确切地说&#xff0c;你不需要在IDE里面编写或者阅读代码。 IDE用于Render资源文件比较合适&#xff0c;但处理文本&#xff0c;并不划算。 这的文本文件&#xff0c;包括源代码&#xff0c;配置文件&#xff0c;文档等非二进制文件。 先说说IDE带的便利: 函数或者变量的自动…

【C++】编程题目分析与实现回顾:从浮点数运算到整型转换的全面解读

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;题目一&#xff1a;计算成绩问题分析与优化实现优化后的实现优势 &#x1f4af;题目二&#xff1a;浮点数向零舍入不同实现方式的比较1. 使用强制类型转换 (int)2. 使用标准…