SpringGateway 网关_spring 网关的作用
liuian 2025-09-13 04:04 31 浏览
奈非框架简介
早期(2020年前)奈非提供的微服务组件和框架受到了很多开发者的欢迎
这些框架和Spring Cloud Alibaba的对应关系我们要知道
Nacos对应Eureka 都是注册中心
Dubbo对应ribbon+feign都是实现微服务间调用
Sentinel对应Hystrix都是项目限流熔断降级组件
Gateway对应zuul都是项目的网关
Gateway不是阿里巴巴的而是Spring提供的
什么是网关
"网关"网是网络,关是关口\关卡
关口\关卡的意思就是"统一入口"
网关:就是网络中的统一入口
程序中的网关就是微服务项目提供的外界所有请求统一访问的微服务项目
因为提供了统一入口之后,方便对所有请求进行统一的检查和管理
网关的主要功能有
- 将所有请求统一由经过网关
- 网关可以对这些请求进行检查
- 网关方便记录所有请求的日志
- 网关可以统一将所有请求路由到正确的模块\服务上
路由的近义词就是"分配"
Spring Gateway简介
我们使用Spring Gateway作为当前项目的网关框架
Spring Gateway是Spring自己编写的,也是SpringCloud中的组件
SpringGateway官网
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/
简单网关演示
网关是一个我们创建的项目,不是一个需要安装的软件
网关也是当前微服务项目的一员,也要注册到Nacos,所以保证Nacos的运行
运行之前,我们看一下网关演示项目已经存在的基本结构
beijing和shanghai是编写好的两个项目
gateway没有编写yml文件配置
要想实现网关的路由效果需要修改yml文件如下
server:
port: 9000
spring:
application:
name: gateway
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
routes: # gateway开始配置路由信息
- id: gateway-shanghai
uri: lb://shanghai
predicates:
- Path=/sh/**
# 如果java访问这个数字元素的方式:spring.cloud.gateway.routes[0].predicates[0]
# routes属性实际上是一个数组,yml文件中出现 "- ...."配置时表示当前配置时一个数组元素
- id: gateway-beijing # 这个配置指定这个路由的名称,这个名称和其他任何位置没有关联
# 只需要注意不能再和其他路由名称重复
# uri设置路由的目标
# lb是LoadBalance(负载均衡)的缩写,beijing是注册到nacos的服务名称
uri: lb://beijing
# 我们需要设置一个条件,当访问路径满足特定条件是,使用当前路由规则
predicates:
# predicates翻译为断言,所谓断言就是判断一个条件是否满足
# Path 是路径断言,意思是满足路径为XXX时使用这个路由
- Path=/bj/**
# http://localhost:9000/bj/show 会路由到 9001/bj/show内置断言
断言就是判断一个条件,如果条件满足就执行某个操作
predicates就是断言的意思
我们前面章节使用的Path就是内置断言中的一种,指访问的路径是否满足条件
除了路径断言之外,还有很多内置断言常见的内置断言列表
- after
- before
- between
- cookie
- header
- host
- method
- path
- query
- remoteaddr
时间相关
after,before,between
在指定时间之后,之前或之间
判断是否满足时间条件,如果满足才允许访问
我们先使用下面代码获得当前包含时区的系统时间表
ZonedDateTime.now()使用After设置必须在指定时间之后访问
- id: gateway-shanghai
uri: lb://shanghai
predicates:
- Path=/sh/**
- After=2022-06-24T15:30:30.999+08:00[Asia/Shanghai]使用Before设置必须在指定时间之后访问
- id: gateway-shanghai
uri: lb://shanghai
predicates:
- Path=/sh/**
- Before=2022-06-24T15:34:00.999+08:00[Asia/Shanghai]使用Between设置必须在指定时间之间访问
- id: gateway-shanghai
uri: lb://shanghai
predicates:
- Path=/sh/**
- Between=2022-06-24T15:34:00.999+08:00[Asia/Shanghai],2022-06-24T15:36:20.999+08:00[Asia/Shanghai]要求指定参数
Query断言,要求必须包含指定的参数才能访问资源
- id: gateway-shanghai
uri: lb://shanghai
predicates:
- Path=/sh/**
- Query=name内置过滤器
Gateway还提供的内置过滤器
不要和我们学习的filter混淆
内置过滤器允许我们在路由请求到目标资源的同时,对这个请求进行一些加工或处理
下面我们使用AddRequestParameter过滤器,想请求中添加参数
- id: gateway-shanghai
uri: lb://shanghai
predicates:
- Path=/sh/**
- Query=name
filters:
- AddRequestParameter=age,80shanghai项目的控制器接收这个参数
@GetMapping("/show")
public String show(String name,Integer age){
return "这里是上海!"+name+","+age;
}重启网关和shanghai项目
例如输入如下路径
http://localhost:9000/sh/show?name=tom
因为过滤器的存在,控制可以获取网关过滤器添加的参数值
其他内置过滤器和自定义过滤器的使用,同学们可以查阅相关文档自己了解
动态路由
如果项目微服务数量多
那么gateway项目yml文件配置也会越来越冗余,维护的工作量也会越来越大
所谓我们希望能够根据固定特征自动的路由到每个微服务模块
这个功能就是SpringGateway的动态路由功能
只需要在配置文件中配置开启动态路由功能即可
spring:
application:
name: gateway
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
discovery:
locator:
# 开启Spring Gateway的动态路由功能
# 规则是根据注册到Nacos的项目名称作为路径的前缀,就可以访问到指定项目了
enabled: true开启之后访问项目的格式以beijing为例
localhost:9000/beijing/bj/show
以下是案例
创建gateway网关子项目
父子相认
子项目pom文件为
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.celinf</groupId>
<artifactId>csmall</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>cn.celinf</groupId>
<artifactId>gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>gateway</name>
<description>Demo project for Spring Boot</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 网负载均衡支持 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!-- Spring Gateway 网关依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--聚合网关 knife4j-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>也删除test测试文件夹
application.yml文件内容如下
spring:
application:
name: gateway-server
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
discovery:
locator:
# 开启网关动态路由
enabled: true
main:
web-application-type: reactive
server:
port: 10000knife4j网关配置
我们希望配置网关之后,在使用knife4j测试时
就不来回切换端口号了
我们需要配置Knife4j才能实现
创建包cn.celinf.gateway.config包
SwaggerProvider
@Component
public class SwaggerProvider implements SwaggerResourcesProvider {
/**
* 接口地址
*/
public static final String API_URI = "/v2/api-docs";
/**
* 路由加载器
*/
@Autowired
private RouteLocator routeLocator;
/**
* 网关应用名称
*/
@Value("${spring.application.name}")
private String applicationName;
@Override
public List<SwaggerResource> get() {
//接口资源列表
List<SwaggerResource> resources = new ArrayList<>();
//服务名称列表
List<String> routeHosts = new ArrayList<>();
// 获取所有可用的应用名称
routeLocator.getRoutes().filter(route -> route.getUri().getHost() != null)
.filter(route -> !applicationName.equals(route.getUri().getHost()))
.subscribe(route -> routeHosts.add(route.getUri().getHost()));
// 去重,多负载服务只添加一次
Set<String> existsServer = new HashSet<>();
routeHosts.forEach(host -> {
// 拼接url
String url = "/" + host + API_URI;
//不存在则添加
if (!existsServer.contains(url)) {
existsServer.add(url);
SwaggerResource swaggerResource = new SwaggerResource();
swaggerResource.setUrl(url);
swaggerResource.setName(host);
resources.add(swaggerResource);
}
});
return resources;
}
}cn.celinf.gateway.controller
SwaggerController类
@RestController
@RequestMapping("/swagger-resources")
public class SwaggerController {
@Autowired(required = false)
private SecurityConfiguration securityConfiguration;
@Autowired(required = false)
private UiConfiguration uiConfiguration;
private final SwaggerResourcesProvider swaggerResources;
@Autowired
public SwaggerController(SwaggerResourcesProvider swaggerResources) {
this.swaggerResources = swaggerResources;
}
@GetMapping("/configuration/security")
public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() {
return Mono.just(new ResponseEntity<>(
Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK));
}
@GetMapping("/configuration/ui")
public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() {
return Mono.just(new ResponseEntity<>(
Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK));
}
@GetMapping("")
public Mono<ResponseEntity> swaggerResources() {
return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
}
}cn.celinf.gateway.filter
SwaggerHeaderFilter类
@Component
public class SwaggerHeaderFilter extends AbstractGatewayFilterFactory {
private static final String HEADER_NAME = "X-Forwarded-Prefix";
private static final String URI = "/v2/api-docs";
@Override
public GatewayFilter apply(Object config) {
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
String path = request.getURI().getPath();
if (!StringUtils.endsWithIgnoreCase(path,URI )) {
return chain.filter(exchange);
}
String basePath = path.substring(0, path.lastIndexOf(URI));
ServerHttpRequest newRequest = request.mutate().header(HEADER_NAME, basePath).build();
ServerWebExchange newExchange = exchange.mutate().request(newRequest).build();
return chain.filter(newExchange);
};
}
}启动Nacos\Seata\Sentinel
启动cart\stock\order\business
在保证一般访问正常的情况下
再启动gateway
可以通过下面路径访问之前的各个模块的业务
http://localhost:10000/nacos-stock/doc.html
http://localhost:10000/nacos-cart/doc.html
http://localhost:10000/nacos-order/doc.html
http://localhost:10000/nacos-business/doc.html
如果不使用网关一切正常,但是启动网关访问失败的话,就是gateway项目配置问题
Gateway和SpringMvc依赖冲突问题和解决
网关依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>SpringMvc依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>这两个依赖在同一个项目中时,默认情况下启动会报错
SpringMvc依赖中自带一个Tomcat服务器
而Gateway依赖中自带一个Netty服务器
因为在启动服务时这个两个服务器都想启动,会因为争夺端口号和主动权而发生冲突
我们需要在yml文件中添加配置解决
spring:
main:
web-application-type: reactive学习记录,如有侵权请联系删除
相关推荐
- 台式电脑如何用u盘重装系统(台式电脑如何用u盘重装系统应用)
-
1、重启电脑并进入BIOS;2、在BIOS中设置启动顺序,优先从U盘启动;3、从U盘启动,进入安装界面;4、选择安装语言、时区和键盘设置;5、选择安装方式,一般选择“清除整个硬盘并安装”;6、配置分区...
-
- stop0x0000007b蓝屏(stop0X0000007b蓝屏,修改注册表)
-
步骤/方式1将电脑送到当地的维修店步骤/方式2然后将师傅维修一下蓝屏的问题当电脑启动蓝屏出现错误代码0x0000007b时,首先我们将电脑重启,在开机时不停按启动热键进入到bios设置页面,进入页面后找到“IntegratedPeriphe...
-
2026-01-14 11:21 liuian
- 怎样设置默认打印机(打印机设置彩色打印在哪里设置)
-
步骤如下:1.单击Windows“开始”菜单,指向“设置”,单击“打印机”,打开“打印机”窗口。2.右键单击打印机图标,系统弹出快速菜单,单击其中的“设为默认值”。如果“打印机”窗口没有当前使用的打印...
- 机械硬盘坏了能修吗(机械硬盘损坏可以修复吗)
-
硬盘修复是很多人都可能会面临的难关。硬盘是计算机上最重要的组成部分,是计算机上的数据存储设备,因此一旦硬盘发生故障,用户很可能会丢失所有数据。况且硬盘是机械设备,有一定的使用寿命,长时间使用出现故障...
- win7正版怎么下载(我告诉你怎么下载win7)
-
如题,题主想在红警之家下载红警,很简单,可以用迅雷下载软件下载,下载以后用解压软件解压就行了,但是红警这款软件在winxp系统下,是最理想的,7系统下面会出现闪退的情况。下载很容易的,闪退的时候,设置...
- 电脑关机脚本bat命令(win10关机bat脚本)
-
bat关机命令需要使用文本文档。使用文本文档制作bat关机命令步骤如下所示:1、在电脑桌面空白处点击鼠标右键。2、在鼠标右键菜单中,选择新建文本文档。3、点击打开文本文档。4、在新建文本文档中输入关机...
- fat32格式是什么意思(u盘fAT32格式是什么意思)
-
是一种分区格式。这种格式使用32位文件分配表,大大提高了磁盘的管理能力,打破了每个分区只有4GB的FAT16限制。对于使用FAT32文件系统的每个逻辑盘内部空间又可划分为三部分,依次是引导区(BOO...
-
- 手机系统更新软件(手机系统更新软件不更新会怎样)
-
第一步:打开苹果手机的设置,点击“通用”选项进入。第二步:选择“软件更新”选项进入第三步:在软件更新界面,如果有新的更新,点击“下载并安装”即可!应用商店里一键更新。在手机软件里,为了更新最新版本可以进软件商店里面找一下,更新点一下,然后它...
-
2026-01-14 09:37 liuian
- 联想小新如何重装系统(联想小新重装系统怎么操作)
-
联想小新重装系统,方法∶在关机状态下,按下电脑的一键恢复按钮(需确保笔记本屏盖在打开状态)。首先找到按键孔,用针对准插孔,捅一下,电脑启动,进入启动选择界面,选择systemrecovery,按回车...
- 麦克风没声音(win11麦克风没声音)
-
一.先确保你的麦克风能正常使用。请确保麦克风本身是好的,连接线没有问题,请确保你的测试软件已正确设置,如YY之类的软件。二.确认你的麦克风是否插入正确的插孔一般麦克风是插入红色插孔中。三.确认你...
- vs2015官网下载(vs2015 下载)
-
VisualStudio2015下载完成之后,会有一个名为“vs2015.pro_chs.iso”的光盘镜像文件。光盘镜像文件将光盘镜像文件在虚拟光驱中加载之后,可以打开查看光盘内容。安装文件双...
- u盘自我保护怎么解除(怎么样取消u盘的自我保护)
-
要解除U盘保护,首先插入U盘后打开“我的电脑”,右击选择U盘图标,点击“属性”。在弹出的对话框中,选择“安全”标签,然后点击“编辑”按钮,根据自己的需要选择或取消“对于系统用户完全控制”权限,点击“确...
- 一周热门
-
-
飞牛OS入门安装遇到问题,如何解决?
-
如何在 iPhone 和 Android 上恢复已删除的抖音消息
-
Boost高性能并发无锁队列指南:boost::lockfree::queue
-
大模型手册: 保姆级用CherryStudio知识库
-
用什么工具在Win中查看8G大的log文件?
-
如何在 Windows 10 或 11 上通过命令行安装 Node.js 和 NPM
-
威联通NAS安装阿里云盘WebDAV服务并添加到Infuse
-
Trae IDE 如何与 GitHub 无缝对接?
-
idea插件之maven search(工欲善其事,必先利其器)
-
如何修改图片拍摄日期?快速修改图片拍摄日期的6种方法
-
- 最近发表
- 标签列表
-
- python判断字典是否为空 (50)
- crontab每周一执行 (48)
- aes和des区别 (43)
- bash脚本和shell脚本的区别 (35)
- canvas库 (33)
- dataframe筛选满足条件的行 (35)
- gitlab日志 (33)
- lua xpcall (36)
- blob转json (33)
- python判断是否在列表中 (34)
- python html转pdf (36)
- 安装指定版本npm (37)
- idea搜索jar包内容 (33)
- css鼠标悬停出现隐藏的文字 (34)
- linux nacos启动命令 (33)
- gitlab 日志 (36)
- adb pull (37)
- python判断元素在不在列表里 (34)
- python 字典删除元素 (34)
- vscode切换git分支 (35)
- python bytes转16进制 (35)
- grep前后几行 (34)
- hashmap转list (35)
- c++ 字符串查找 (35)
- mysql刷新权限 (34)
