【Zero to One系列】SpringCloud Gateway结合Nacos完成微服务的网关路由

前期回顾:

【Zero to One系列】springcloud微服务集成nacos,形成分布式系统


1、Gateway依赖配置

主要Maven依赖如下:

<dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId><version>2.2.5.RELEASE</version></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId><version>2.2.5.RELEASE</version></dependency>
</dependencies>

在Gateway的启动类上,需要加上注解:

@EnableDiscoveryClient


2、Gateway路由配置

网关在nacos上注册配置:

spring:cloud:nacos:discovery:server-addr: ip:8848namespace: a663dc6b-98ff-4518-9a06-ffb3e3c4b697group: ***-dev

然后是路由配置,如下:

spring:application:name: ***-gatewaycloud:gateway:routes: - id : ***-useruri : lb://***-user  #在服务注册中心找服务名为 ***-user 的服务predicates : - Path= /user/*    #设置路由断言,当请求 /user 时进行转发- id : ***-senduri : lb://***-send  #在服务注册中心找服务名为 ***-user 的服务predicates : - Path= /send/*    #设置路由断言,当请求 /send 时进行转发 

路由规则的配置说明,主要有上面写的这部分。如果需要写的更特殊化一些,可以参考gateway的路由配置说明参考链接:spring cloud gateway核心概念之断言和过滤器


3、使用Nacos配置路由

        在一般系统开发中,微服务子模块,可能会比较多。当配置路由时,可能有较高评率的更新变动,如果像上述方式,放在系统的配置文件中,那每次修改,都得重新发布网关服务,所以不太合适。因此,我们可以将服务的路由配置放在Nacos的配置文件中,如此可以随时修改和更新啦。

        首先,我们在nacos上建一个网关的配置文件,如gateway.yml文件,文件内容如下:

spring:application:name: ***-gatewaycloud:gateway:routes: - id : ***-useruri : lb://***-user  #在服务注册中心找服务名为 ***-user 的服务predicates : - Path= /user/*    #设置路由断言,当请求 /user 时进行转发- id : ***-senduri : lb://***-send  #在服务注册中心找服务名为 ***-send 的服务predicates : - Path= /send/*    #设置路由断言,当请求 /send 时进行转发 

然后,我们需要在服务的pom依赖中有config的依赖,

<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId><version>2.2.5.RELEASE</version>
</dependency>

最后,配置对应的nacos配置文件即可,如下:

spring:cloud:nacos:discovery:server-addr: ip:8848namespace: a663dc6b-98ff-4518-9a06-ffb3e3c4b697group: ***-devconfig: #config配置必须放在bootstrap配置内,才能读取到nacos配置,否则报错server-addr: ip:8848namespace: a663dc6b-98ff-4518-9a06-ffb3e3c4b697group: ***-devprefix: gatewayfile-extension: ymlrefresh-enabled: true

此处需要着重注意:config相关的配置,必须放在bootstrap的yml或properties文件中,因为bootstrap的优先级最高,否则启动会因读取不到nacos上的配置数据。。(我实践时就是在这里,测试了好一阵。。。)


4、Gateway全局过滤处理

Gateway有一个全局过滤接口GlobalFilter,实现其filter方法,就可以加入一些我们代码逻辑的自定义处理了,例如:

package com.***.gateway.filter;import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;/*** @Description 与 GatewayFilter 的作用一样。* 区别在于 GlobalFilter 的逻辑可以写代码来自定义规则;* 而 GatewayFilter 通过配置定义,处理逻辑是固定的。*/
public class GatewayFilter implements GlobalFilter,Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//todo 例如请求加解密处理、白名单校验等等return chain.filter(exchange);}//设置过滤器优先级,值越低优先级越高@Overridepublic int getOrder() {return 0;}
}

此处过滤处理的细节实现,此处暂不展开,后续博文中,我会陆续输出,感兴趣请关注一下我相关系列的博文吧!!


5、异常情况说明

gateway启动异常,异常信息如下:

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2023-03-23 10:29:03.849 ERROR 36416 --- [  restartedMain] o.s.boot.SpringApplication               : Application run failedreactor.core.Exceptions$ErrorCallbackNotImplemented: java.lang.IllegalArgumentException: Unable to find RoutePredicateFactory with name Path 
Caused by: java.lang.IllegalArgumentException: Unable to find RoutePredicateFactory with name Path at org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator.lookup(RouteDefinitionRouteLocator.java:264) ~[spring-cloud-gateway-core-2.2.2.RELEASE.jar:2.2.2.RELEASE]at org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator.combinePredicates(RouteDefinitionRouteLocator.java:244) ~[spring-cloud-gateway-core-2.2.2.RELEASE.jar:2.2.2.RELEASE]at org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator.convertToRoute(RouteDefinitionRouteLocator.java:169) ~[spring-cloud-gateway-core-2.2.2.RELEASE.jar:2.2.2.RELEASE]at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:100) ~[reactor-core-3.3.13.RELEASE.jar:3.3.13.RELEASE]at reactor.core.publisher.FluxFlatMap$FlatMapMain.tryEmitScalar(FluxFlatMap.java:480) ~[reactor-core-3.3.13.RELEASE.jar:3.3.13.RELEASE]at reactor.core.publisher.FluxFlatMap$FlatMapMain.onNext(FluxFlatMap.java:413) ~[reactor-core-3.3.13.RELEASE.jar:3.3.13.RELEASE]at reactor.core.publisher.FluxFlatMap$FlatMapMain.drainLoop(FluxFlatMap.java:704) ~[reactor-core-3.3.13.RELEASE.jar:3.3.13.RELEASE]at reactor.core.publisher.FluxFlatMap$FlatMapMain.drain(FluxFlatMap.java:580) ~[reactor-core-3.3.13.RELEASE.jar:3.3.13.RELEASE]at reactor.core.publisher.FluxFlatMap$FlatMapInner.onSubscribe(FluxFlatMap.java:970) ~[reactor-core-3.3.13.RELEASE.jar:3.3.13.RELEASE]at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:161) ~[reactor-core-3.3.13.RELEASE.jar:3.3.13.RELEASE]at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:86) ~[reactor-core-3.3.13.RELEASE.jar:3.3.13.RELEASE]at reactor.core.publisher.Flux.subscribe(Flux.java:8357) ~[reactor-core-3.3.13.RELEASE.jar:3.3.13.RELEASE]at reactor.core.publisher.FluxFlatMap$FlatMapMain.onNext(FluxFlatMap.java:418) ~[reactor-core-3.3.13.RELEASE.jar:3.3.13.RELEASE]at reactor.core.publisher.FluxIterable$IterableSubscription.slowPath(FluxIterable.java:267) ~[reactor-core-3.3.13.RELEASE.jar:3.3.13.RELEASE]at reactor.core.publisher.FluxIterable$IterableSubscription.request(FluxIterable.java:225) ~[reactor-core-3.3.13.RELEASE.jar:3.3.13.RELEASE]at reactor.core.publisher.FluxFlatMap$FlatMapMain.onSubscribe(FluxFlatMap.java:363) ~[reactor-core-3.3.13.RELEASE.jar:3.3.13.RELEASE]at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:161) ~[reactor-core-3.3.13.RELEASE.jar:3.3.13.RELEASE]at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:86) ~[reactor-core-3.3.13.RELEASE.jar:3.3.13.RELEASE]at reactor.core.publisher.Flux.subscribe(Flux.java:8357) ~[reactor-core-3.3.13.RELEASE.jar:3.3.13.RELEASE]at reactor.core.publisher.FluxFlatMap$FlatMapMain.onNext(FluxFlatMap.java:418) ~[reactor-core-3.3.13.RELEASE.jar:3.3.13.RELEASE]at reactor.core.publisher.FluxIterable$IterableSubscription.slowPath(FluxIterable.java:267) ~[reactor-core-3.3.13.RELEASE.jar:3.3.13.RELEASE]at reactor.core.publisher.FluxIterable$IterableSubscription.request(FluxIterable.java:225) ~[reactor-core-3.3.13.RELEASE.jar:3.3.13.RELEASE]at reactor.core.publisher.FluxFlatMap$FlatMapMain.onSubscribe(FluxFlatMap.java:363) ~[reactor-core-3.3.13.RELEASE.jar:3.3.13.RELEASE]at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:161) ~[reactor-core-3.3.13.RELEASE.jar:3.3.13.RELEASE]at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:86) ~[reactor-core-3.3.13.RELEASE.jar:3.3.13.RELEASE]at reactor.core.publisher.Mono.subscribe(Mono.java:4252) ~[reactor-core-3.3.13.RELEASE.jar:3.3.13.RELEASE]at reactor.core.publisher.Mono.subscribeWith(Mono.java:4363) ~[reactor-core-3.3.13.RELEASE.jar:3.3.13.RELEASE]at reactor.core.publisher.Mono.subscribe(Mono.java:4083) ~[reactor-core-3.3.13.RELEASE.jar:3.3.13.RELEASE]at org.springframework.cloud.gateway.route.CachingRouteLocator.onApplicationEvent(CachingRouteLocator.java:73) ~[spring-cloud-gateway-core-2.2.2.RELEASE.jar:2.2.2.RELEASE]at org.springframework.cloud.gateway.route.CachingRouteLocator.onApplicationEvent(CachingRouteLocator.java:35) ~[spring-cloud-gateway-core-2.2.2.RELEASE.jar:2.2.2.RELEASE]at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE]at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE]at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE]at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:404) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE]at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:361) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE]at org.springframework.cloud.gateway.route.RouteRefreshListener.reset(RouteRefreshListener.java:68) ~[spring-cloud-gateway-core-2.2.2.RELEASE.jar:2.2.2.RELEASE]at org.springframework.cloud.gateway.route.RouteRefreshListener.onApplicationEvent(RouteRefreshListener.java:49) ~[spring-cloud-gateway-core-2.2.2.RELEASE.jar:2.2.2.RELEASE]at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE]at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE]at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE]at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:404) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE]at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:361) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE]at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:898) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE]at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.finishRefresh(ReactiveWebServerApplicationContext.java:129) ~[spring-boot-2.2.13.RELEASE.jar:2.2.13.RELEASE]at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:554) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE]at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.refresh(ReactiveWebServerApplicationContext.java:66) ~[spring-boot-2.2.13.RELEASE.jar:2.2.13.RELEASE]at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) [spring-boot-2.2.13.RELEASE.jar:2.2.13.RELEASE]at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:405) [spring-boot-2.2.13.RELEASE.jar:2.2.13.RELEASE]at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-2.2.13.RELEASE.jar:2.2.13.RELEASE]at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) [spring-boot-2.2.13.RELEASE.jar:2.2.13.RELEASE]at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) [spring-boot-2.2.13.RELEASE.jar:2.2.13.RELEASE]at com.***.gateway.***GatewayApplication.main(***GatewayApplication.java:12) [classes/:na]at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_241]at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_241]at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_241]at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_241]at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) [spring-boot-devtools-2.2.13.RELEASE.jar:2.2.13.RELEASE]Disconnected from the target VM, address: '127.0.0.1:2687', transport: 'socket'
2023-03-23 10:29:03.856  WARN 36416 --- [      Thread-10] c.a.n.common.http.HttpClientBeanHolder   : [HttpClientBeanHolder] Start destroying common HttpClient
2023-03-23 10:29:03.857  WARN 36416 --- [      Thread-10] c.a.n.common.http.HttpClientBeanHolder   : [HttpClientBeanHolder] Destruction of the endProcess finished with exit code 0

这个问题,报错信息是:Unable to find RoutePredicateFactory with name Path 

其实是一个路由配置的格式问题导致,解决方式就是必须严格注意以下2点:

1、Path的首字母必须大写

2、- Path= 这个等于号前面,不能有空格

另一个异常,可能会报:

Cannot determine local hostname

需要在配置中加上如下内容:

spring:cloud:inetutils:ignored-interfaces: 'VMware Virtual Ethernet Adapter for VMnet1,VMware Virtual Ethernet Adapter for VMnet8'

        至此,Gateway网关对于微服务的路由配置实现,就基本完成啦!!!

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

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

相关文章

oracle date类型如何比较时间

在 Oracle 数据库中&#xff0c;如果你想要比较 DATE 类型的时间部分&#xff0c;你需要意识到 DATE 类型实际上包含日期和时间信息&#xff0c;精确到秒。但是&#xff0c;由于 DATE 类型没有单独的时间组件&#xff0c;你通常需要一些额外的逻辑来提取或比较时间部分。 以下…

文章解读与仿真程序复现思路——电力系统自动化EI\CSCD\北大核心《考虑发用电相似性的海上风电中长期双边协商交易优化决策模》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

小鸡庄园智慧农场养殖游戏开发:科技与农业的完美结合

随着科技的进步&#xff0c;一种全新的游戏模式——智慧农场养殖游戏&#xff0c;正在逐渐崭露头角。本文将深入探讨小鸡庄园智慧农场养殖游戏的开发背景、特点、技术实现方式以及未来的发展趋势&#xff0c;以期为游戏产业创新和农业现代化提供新的思路和启示。 一、开发背景…

Rust 性能分析

都说Rust性能好,但是也得代码写得好,猜猜下面两个代码哪个快 . - 力扣&#xff08;LeetCode&#xff09; use std::collections::HashMap; use lazy_static::lazy_static;lazy_static! {static ref DIGIT: HashMap<char, usize> {let mut m HashMap::new();for c in …

【Nacos】docker-compose启动nacos v2.2.3,启动时修改默认密码不使用naocs

1. 背景 出于安全考虑&#xff0c;我司DevOps平台自动部署的容器化nacos密码不能是弱密码或默认值 但是nacos-v2.2.3官方镜像启动后会初始化nacos用户密码为nacos&#xff0c;修改启动时的变量并没有生效。 2. 部署验证 2.1 yml文件如下 注意将derby库的初始化文件挂载出来…

探索Linux中的fdisk命令:磁盘分区管理的利器

探索Linux中的fdisk命令&#xff1a;磁盘分区管理的利器 在Linux系统管理中&#xff0c;磁盘分区是一项非常重要的任务。它涉及到数据的存储、备份和恢复&#xff0c;以及系统的性能和稳定性。而fdisk&#xff0c;作为Linux下的一款经典磁盘分区工具&#xff0c;凭借其强大的功…

软件测试学习总结-侧开之路的起点

软件测试学习总结-侧开之路的起点 文章目录 一、软件测试的基础理论知识 1、软件测试初了解 2、阅读和梳理需求⽂档 3、测试用例编写 4、缺陷管理 二、Linux系统学习 1、Linux系统学习 三、MySQL数据库学习 1、MySQL数据库学习 四、MySQL数据库学习 1、MySQL数据库学习 …

Python | Leetcode Python题解之第129题求根节点到叶节点数字之和

题目&#xff1a; 题解&#xff1a; class Solution:def sumNumbers(self, root: TreeNode) -> int:if not root:return 0total 0nodeQueue collections.deque([root])numQueue collections.deque([root.val])while nodeQueue:node nodeQueue.popleft()num numQueue.p…

产品人生(9):从“波士顿矩阵”看“个人职业规划”

波士顿矩阵&#xff08;简称BCG矩阵&#xff09;是一种战略规划工具&#xff0c;由波士顿咨询公司的创始人布鲁斯亨德森&#xff08;Bruce Henderson&#xff09;于1970年代初提出的&#xff0c;它以两个关键指标作为分析维度&#xff1a;市场增长率和相对市场份额&#xff0c;…

探索k8s集群的配置资源(secret和configmap)

目录 ConfigMap ConfigMap&#xff08;主要是将配置目录或者文件挂载到k8s里面使用&#xff09; 与Secret类似&#xff0c;区别在于ConfigMap保存的是不需要加密配置的信息。&#xff08;例如&#xff1a;配置文件&#xff09; ConfigMap 功能在 Kubernetes1.2 版本中引入&…

过期视频怎么恢复?如何从手机、电脑和其他设备中恢复?

过期视频是指那些被误删、丢失或因系统升级等原因而无法正常访问的视频文件。这些视频可能包含了我们珍贵的回忆、重要的信息或者具有商业价值的内容。过期视频的恢复可以帮助我们找回失去的数据&#xff0c;减少损失&#xff0c;提高工作效率和生活质量。过期视频怎么恢复&…

Android WebView上传文件/自定义弹窗技术,附件的解决方案

安卓内核开发 其实是Android的webview默认是不支持<input type"file"/>文件上传的。现在的前端页面需要处理的是&#xff1a; 权限 文件路径AndroidManifest.xml <uses-permission android:name"android.permission.WRITE_EXTERNAL_STORAGE"/&g…

【AI基础】第二步:安装AI运行环境

开局一张图&#xff1a; 接下来按照从下往上的顺序来安装部署。 规则1 注意每个层级的安装版本&#xff0c;上层的版本由下层版本决定 比如CUDA的版本&#xff0c;需要看显卡安装了什么版本的驱动&#xff0c;然后CUDA的版本不能高于这个驱动的版本。 这个比较好理解&#xff…

毕业论文word常见问题

0、前言&#xff1a; 这里的问题都是以office办公软件当中的word为例&#xff0c;和WPS没有关系。 1、页眉横线删不掉&#xff1a; 解决方案&#xff1a;进入页眉编辑状态&#xff0c;在开始选项栏中选择页眉字体样式&#xff0c;清除格式。 修改方式如下&#xff1a; 2、…

mysql inset bug

在 SQL 中&#xff0c;日期值需要用单引号包围&#xff0c;这是因为 SQL 将日期值视为字符串格式。数据库引擎在处理这些值时会将它们解析为适当的日期类型。如果不使用单引号&#xff0c;数据库引擎会将它们视为数字或列名&#xff0c;从而导致语法错误。 日期格式 MySQL 支…

在Linux/Ubuntu/Debian系统中使用 `tar` 压缩文件

在Linux/Ubuntu/Debian系统中使用 tar 压缩文件 tar 命令是用于在类 Unix 操作系统中创建文件和目录存档的强大实用程序。 基本存档创建 要创建文件夹的简单存档&#xff0c;请使用以下命令&#xff1a; tar -cf ./my-archive.tar ./my-folder/此命令将创建一个名为 my-arc…

java入门 Netty ByteBuf

一、 参考资料 参考黑马netty教程 https://www.bilibili.com/video/BV1py4y1E7oA?p88&spm_id_frompageDriver&vd_source4cd1b6f268e2a29a11bea5d2568836ee 二、 ByteBuf测试 app.java package com.sht.test;import io.netty.buffer.ByteBuf; import io.netty.buff…

Android基础-Jetpack Compose

Jetpack Compose&#xff0c;作为Android平台上一款革命性的UI框架&#xff0c;自其推出以来就受到了广大开发者的热烈关注和广泛应用。它不仅简化了Android应用的UI开发流程&#xff0c;提高了开发效率&#xff0c;而且为开发者带来了更直观、更灵活、更强大的UI定义方式。下面…

Linux——简单指令汇总

Linux&#xff0c;一般指GNU/Linux&#xff0c;是一种免费使用和自由传播的类UNIX操作系统&#xff0c;其内核由林纳斯本纳第克特托瓦兹&#xff08;Linus Benedict Torvalds&#xff09;于1991年10月5日首次发布&#xff0c;它主要受到Minix和Unix思想的启发&#xff0c;是一个…

C++ | Leetcode C++题解之第130题被围绕的区域

题目&#xff1a; 题解&#xff1a; class Solution { public:const int dx[4] {1, -1, 0, 0};const int dy[4] {0, 0, 1, -1};void solve(vector<vector<char>>& board) {int n board.size();if (n 0) {return;}int m board[0].size();queue<pair<…