分析JS Crash(进程崩溃)

news2024/10/6 7:28:30

一、JS Crash异常检测能力

        1、JS Crash日志规格

        以下是进程崩溃日志信息中对应字段解释。

Build info:XXX-XXXX X.X.X.XX(XXXXXXXX) <- 版本信息
Module name:com.example.myapplication <- 模块名
Version:1.0.0 <- 版本号
Pid:579 <- 进程号
Uid:0 <- 用户ID
Reason:TypeError <- 原因
Error message:Cannot read property c of undefined <- 异常信息
Cannot get SourceMap info, dump raw stack: <- 应用安装包为release包安装时不包含sourcemap文件,JS栈通过sourcemap行列号解析会失败
SourceCode:
        var a = b.c;   <- 异常代 码位置
                ^
Stacktrace:
    at onPageShow (entry/src/main/ets/pages/Index.ets:7:13)  <-异常代 码调用栈
           ^                                      ^
         函数名异常代 码文件行列号位置

        JS Crash多为应用问题,开发者可通过崩溃文件中的 Error message 和 StackTrace 来定位问题。 

        2、JS Crash异常捕获场景

        JS Crash异常根据不同的异常场景,在 Reason 字段进行了分类,分为Error、TypeError、SyntaxError、RangeError等错误类型。

  • 自定义 Error 类:Error 是最基本的错误类型,其他的错误类型都继承自该类型。Error 对象主要有两个重要属性 message 和 name 分别表示错误信息和错误名称。程序运行过程中抛出的异常一般都有具体的类型,Error 类型一般都是开发人员自己抛出的异常。

  • TypeError(类型错误)类:运行时最常见的异常,表示变量或参数不是预期类型。

  • SyntaxError(语法错误)类:语法错误也称为解析错误。语法错误在任何编程语言中都是最常见的错误类型,表示不符合编程语言的语法规范。

  • RangeError(边界错误)类:表示超出有效范围时发生的异常,主要的有以下几种情况:

    • 数组长度为负数或超长
    • 数字类型的方法参数超出预定义范围
    • 函数堆栈调用超过最大值
  • ReferenceError —— 引用错误:引用一个不存在的变量时发生的错误,每当我们创建一个变量时,变量名称都会写入一个变量存储中心中,这个变量存储中心就像键值存储一样,每当我们引用变量时,它都去存储中找到 key并提取并返回 value,如果我们要找的变量不在存储中,就会抛出 ReferenceError。

  • URI Error —— URL错误:在调用 URI 相关的方法中 URL 无效时抛出的异常,主要包括 encodeURI()、decodeURI()、encodeURIComponent()、decodeURIComponent()、escape() 和 unescape() 几个函数 。

二、问题定位思路

        1、获取日志

        (1)通过DevEco Studio获取日志

        DevEco Studio会收集设备“/data/log/faultlog/faultlogger/”路径下的进程崩溃故障日志并归档在FaultLog下。

        (2)通过hiAppEvent接口订阅

        hiAppEvent 提供了故障订阅接口,可以订阅各类故障打点。

        2、根因分析

        JS Crash问题分析一般根据上述异常的场景,结合错误信息、调用栈定位到源码,可得出基本的分析结论。对于调用栈的分析有以下几种情况。

        (1)StackTrace 场景分类

        JS Crash故障日志中,StackTrace 字段存放的是 JS Crash 异常的调用栈信息,StackTrace 的显示分为以下几种场景:

        a、JS调用栈可直接通过超链接跳转到对应错误代 码行,栈顶即为问题第一现场,如下样例所示 

Device info:xxx
Build info:xxx-xxx x.x.x.xxx(xxxx)
Fingerprint:ed1811f3f5ae13c7262b51aab73ddd01df95b2c64466a204e0d70e6461cf1697
Module name:com.xxx.xxx
Version:1.0.0
VersionCode:1000000
PreInstalled:No
Foreground:Yes
Pid:31255
Uid:20020145
Reason:Error
Error name:Error
Error message:JSERROR
Sourcecode:
                throw new ErrOr("JSERROR");
                      ^
Stacktrace:
    at anonymous (entry/src/main/ets/pages/Index.ets:13:19)

        b、异常代 码调用栈 Stack Cannot get SourceMap info, dump raw stack,表示因SourceMap转换失败,仅展示eTS栈对应编译后产物中代 码行号,可通过超链接跳转到对应错误代 码行,如下样例所示。

Device info:xxx
Build info:xxx-xxx x.x.x.xxx(xxxx)
Fingerprint:a370fceb59011d96e41e97bda139b1851c911012ab8c386d1a2d63986d6d226d
Module name:com.xxx.xxx
Version:1.0.0
Versioncode:1000000
PreInstalled:No
Foreground:Yes
Pid:39185
Uid:20020145
Reason:Error
Error name:Error
Error message:JSERROR
Stacktrace:
Cannot get SourceMap info, dump raw stack:
    at anonymous (entry/src/main/ets/paqes/Index.ts:49:49)

        c、异常代 码调用栈包含 SourceMap is not initialized yet ,表示因SourceMap转换非常耗时,改为通过异步线程去进行初始化,导致会出现SourceMap没初始化完成就有异常产生的情况。针对这种情况增加这行日志来提示开发者。eTS栈对应编译后产物中代 码行号,可通过超链接跳转到对应错误代 码行。如下样例所示。

Device info:xxx
Build info:xxx-xxx x.x.x.xxx(xxxx)
Fingerprint:377ef8529301363f373ce837d0bf83aacfc46112502143237e2f4026e86a0510
Module name:com.xxx.xxx
Version:1.0.0
Versioncode:1000000
PreInstalled:No
Foreground:Yes
Pid:6042
Uid:20020145
Reason:Error
Error name:Error
Error message:JSERROR
Sourcecode:
            throw new Error("JSERROR");
                  ^
Stacktrace:
SourceMap is not initialized yet
at anonymous (entry/src/main/ets/pages/Index.ts:49:49)

        d、异常代 码调用栈中打印native栈,栈顶一般为libark_jsruntime.so动态库,这是因为JS异常最后都会经过虚拟机抛出。从崩溃栈从上往下找,libace_napi.z.so的上一帧一般是抛出异常的现场。如下样例所示。

Device info:xxx
Build info:xxx-xxx x.x.x.xxx(xxxx)
Fingerprint:89f2b64b24d642b0fc64e3a7cf68ca39fecaa580ff5736bb9d6706ea4cdf2c93
Module name:com.xxx.xxx
Version:1.0.0
VersionCode:1000000
PreInstalled:No
Foreground:No
Pid:14325
Uid:20020145
Reason:ReferenceError
Error name:ReferenceError
Error message:Cannot find module 'com.xxx.xxx/entry/EntryAbility' , which is application Entry Point
Stacktrace:
SourceMap is not initialized yet
#01 pc 000000000028ba3b /system/libó4/platformsdk/libark_jsruntime.so(bf6ea8e474ac3e417991f101e062fa90)
#02 pc 00000000001452ff /system/libó4/platformsdk/libark_jsruntime.so(bf6ea8e474ac3e417991f101e062fa90)
#03 pC 0000000000144c9f /system/libó4/platformsdk/libark_jsruntime.so(bf6ea8e474ac3e417991f101e062fa90)
#04 pc 00000000001c617b /system/libó4/platformsdk/libark_jsruntime.so(bf6ea8e474ac3e417991f101e062fa90)
#05 pc 00000000004c3cb7 /system/libó4/platformsdk/libark_jsruntime.so(bf6ea8e474ac3e417991f101e062fa90)
#06 pc 00000000004c045f /system/libó4/platformsdk/libark_jsruntime.so(bf6ea8e474ac3e417991f101e062fa90)
#07 pc 000000000038034f /system/libó4/platformsdk/libark_jsruntime.so(bf6ea8e474ac3e417991f101e062fa90)
#08 pc 00000000004b2d9b /system/libó4/platformsdk/libark_jsruntime.so(bf6ea8e474ac3e417991f101e062fa90)
#09 pc 0000000000037e7f /system/libó4/platformsdk/libace_napi.z.so(10ceafd39b5354314d2fe3059b8f9e4f)
#10 pc 00000000000484cf /system/lib64/platformsdk/libruntime.z.so(3f6305a3843fae1de148a06eec4bd014) <- 异常抛出位置
#11 pc 000000000004fce7 /system/libó4/platformsdk/libruntime.z.so(3f6305a3843fae1de148a06eec4bd014)
#12 pc 000000000004e9fb /system/libó4/platformsdk/libruntime.z.so(3f6305a3843fae1de148a06eec4bd014)
#13 pc 000000000004eb7b /system/libó4/platformsdk/libruntime.z.so(3f6305a3843fae1de148a06eec4bd014)
#14 pc 000000000004f5c7 /system/libó4/platformsdk/libruntime.z.so(3f6305a3843fae1de148a06eec4bd014)
#15 pc 00000000000303cf /system/lib64/platformsdk/libuiabilitykit_native.z.so(3203F4CCe84a43b519d0a731dfOdb1a3)

        (2)调用栈分析

        a、可跳转至引起错误的代 码行

        如果FaultLog的堆栈信息中的链接或偏移地址指向的是当前工程中的某行代 码,该段信息将被转换为超链接形式,在DevEco Studio中点击后跳转至对应代 码行。

        b、不可跳转至引起错误的代 码行或者跳转代 码位置不存在

        如出现Cannot get Source Map info, dump raw stack信息代表js栈转换ets行列号失败,在DevEco Studio中点击链接会跳转到不正确的代 码位置或不存在的代 码行位置。

        应用代 码运行出错时,会打印错误栈信息。如果ts栈转换ets行列号失败时错误栈的后缀仍显示为ets,开发者需要在build目录下编译中间产物以生成ts代 码,在js代 码中定位对应错误代 码行。

三、分析案例

        1、TypeError类案例分析

        TypeError类问题在实际应用开发调试运行过程中是最常见的JS Crash类型,其表示为变量不是预期类型,在代 码层面则为对变量的使用未进行事先的校验,在错误日志中报错多表现为如下:

Error name:TypeError
Error message:Cannot read property xxx of undefined

        (1)更新跟手动效相关属性时偶现JS Crash

        a、获取JS Crash日志如下
Generated by HiviewDFX@HarmonyOS
================================================================
Device info:xxxx
Build info:xxxx
Fingerprint:9851196f9fed7fd818170303296ae7a5767c9ab11f38fd8b0072f0e32c42ea39
Module name:com.xxx.xxx
Version:1.0.0.29
VersionCode:10000029
PreInstalled:Yes
Foreground:No
Pid:2780
Uid:20020018
Reason:TypeError
Error name:TypeError
Error message:Cannot read property needRenderTranslate of undefined
Stacktrace:
Cannot get SourceMap info, dump raw stack:
    at updateGestureValue (phone/src/main/ets/SceneBoard/recent/scenepanel/recentpanel/RecentGesture.ts:51:51)
    at onRecentGestureActionBegin (phone/src/main/ets/SceneBoard/scenemanager/SCBScenePanel.ts:5609:5609)
    at anonymous (phone/src/main/ets/SceneBoard/scenemanager/SCBScenePanel.ts:555:555)
    at anonymous (phone/src/main/ets/SceneBoard/recent/RecentEventView.ts:183:183)
       b、提取日志关键信息

        通过日志信息可以确定为Type Error类问题,由异常信息得知是在读取needRenderTranslate对象时报错,该对象为undefined。最后可以通过异常代 码调用栈,获取错误产生位置。

        Cannot get SourceMap info, dump raw stack 信息表示该应用为release包安装,JS栈转换eTS行列号失败,可考虑使用应用堆栈解析来解析行号。 

        (1)定位到具体代 码

        通过以上 JS 堆栈和报错变量分析,能够定位到具体函数示例如下:

  // 更新与跟手动效相关的属性
  public updateGestureValue(screenWidth: number, recentScale: number, sceneContainerSessionList: SCBSceneContainerSession[]) {
    // 跟手移动的距离计算
    this.translationUpY = (this.multiCardsNum >= 1) ? sceneContainerSessionList[this.multiCardsNum - 1].needRenderTranslate.translateY : 0;    ---> 报错行号
    this.translationDownY = (this.multiCardsNum >= 2) ? sceneContainerSessionList[this.multiCardsNum - 2].needRenderTranslate.translateY : 0;
    this.screenWidth = px2vp(screenWidth);
    this.recentScale = recentScale;
  }

        (2)修改方案

        上述分析已经明确为 sceneContainerSessionList 的成员变量 needRenderTranslate 在使用的过程中可能存在为 undefined 的情况。对于这类问题,需要增加保护性判断,可直接规避此类问题。具体修改方法可以如下,在访问对象前增加 '?' 操作符进行判断保护。

        (3)思考与建议

        对于这类问题,需要我们在编码阶段充分考虑对象访问的安全性,确保必要的判空处理。同时很多场景单纯的判空可能只能是规避问题,还需要结合业务看看是否是原始对象构造或赋值的逻辑存在问题。

        2、Error 类案例分析

        Error 类问题一般是开发者或JS库主动抛出来的JS异常。

        这类问题目前有两种场景:

        a、如果是当前应用程序遇到无法解决的只能终止当前业务的故障,需要考虑抛出JS异常来终止业务并生成故障日志。

        b、依赖使用JS库或者其他的模块接口,对于可能抛出异常的接口,需要考虑使用 try-catch 机制进行捕获,否则也会终止当前业务。

        (1)如何主动抛出一个自定义的JS异常来终止程序

        开发者自主抛出JS异常,可通过如下代 码实现:

throw new Error("TEST JS ERROR")

        通过上述开发过程基于 DevEco Studio FaultLog工具收集到的故障日志,可以基于JS异常栈直接定位到抛异常的位置。

        

        遇到这类问题的解决思路,仍旧是通过故障日志定位到具体的代 码行,检视上下文来分析问题即可。

        (2)因未处理三方接口抛出的JS异常导致的JS Crash问题

        a、获取JS Crash 日志核心内容如下
Error name:Error
Error message:BussinessError 2501000: Operation failed.
Error code:2501000
Stacktrace:
Cannot get SourceMap info, dump raw stack:
  at onStart (product/phone/build/default/cache/default/default@CompileArkTS/esmodule/release/feature/systemstatus/linkspeedcomponent/src/main/ets/default/controller/NetSpeedController.ts:50:1)
  at NetSpeedController (product/phone/build/default/cache/default/default@CompileArkTS/esmodule/release/feature/systemstatus/linkspeedcomponent/src/main/ets/default/controller/NetSpeedController.ts:43:43)
  at getInstance (product/phone/build/default/cache/default/default@CompileArkTS/esmodule/release/staticcommon/basiccommon/src/main/ets/component/utils/SingletonHelper.ts:17:17)
  at func_main_0 (product/phone/build/default/cache/default/default@CompileArkTS/esmodule/release/feature/systemstatus/linkspeedcomponent/src/main/ets/default/controller/NetSpeedController.ts:325:325)
        b、提取日志关键信息 

        通过日志信息可以确定为 Error 类问题,为代 码主动抛出的异常。最后可以通过异常代 码调用栈,获取错误产生位置。

        Cannot get SourceMap info, dump raw stack 信息表示该应用为release包安装,JS栈转换eTS行列号失败,可考虑使用应用堆栈解析来解析行号。

        a、定位到具体代 码

        通过以上 JS 堆栈,能够定位到 NetSpeedController.ts 文件中具体代 码片段如下,异常抛出位置为 wifiManager.on 函数调用。

onStart(): void {
  super.onStart();
  log.showInfo('onStart');
  ...
  wifiManager.on('wifiConnectionChange', (data) => {
    this.isConnected = data === 1 ? true : false;
    this.handleUpdateState();
  });
  wifiManager.on('wifiStateChange', (data) => {
    this.isWifiActive = data === 1 ? true : false;
    this.handleUpdateState();
  });
  ...
}
        b、修改方案

        通过分析 wifiManager.on 源码,得知该函数内存在部分场景会抛出内容为 BussinessError 2501000: Operation failed. 的 JS 异常,对于此类问题,识别当前业务异常不会导致当前程序无法运行下去,考虑使用 try-catch 机制对异常进行捕获处理。具体的修改方法可参考如下:

onStart(): void {
  super.onStart();
  log.showInfo('onStart');
  ...
  try {
    wifiManager.on('wifiConnectionChange', (data) => {
      this.isConnected = data === 1 ? true : false;
      this.handleUpdateState();
    });
  } catch (error) {
    log.showError('wifiConnectionChange error');
  }
  try {
    wifiManager.on('wifiStateChange', (data) => {
      this.isWifiActive = data === 1 ? true : false;
      this.handleUpdateState();
    });
  } catch (error) {
    log.showError('wifiStateChange error');
  }
  ...
}
        c、思考与建议

        对于这类问题,我们可以考虑在编码阶段灵活的运用 JS 异常机制,来识别各类异常场景;同时对于使用可能会抛异常的接口,也需要考虑是否需要捕获该异常,避免影响应用主体业务。

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

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

相关文章

【Qt】Qt学习笔记(一):Qt界面初识

Qt 是一个跨平台应用程序和 UI 开发框架。使用 Qt 您只需一次性开发应用程序&#xff0c;无须重新编写源代码&#xff0c;便可跨不同桌面和嵌入式操作系统部署这些应用程序。Qt Creator是跨平台的Qt集成开发环境。 创建项目 Qt的一些界面&#xff0c;初学时一般选择Qt Widgets …

VirtualBox虚拟机连接宿主机并能够上网(小白向)

现存问题 windows系统主要使用vmare和virtualbox两种虚拟机&#xff0c;virtualbox相对于vmare更加轻便&#xff0c;但少有博客能够详细说明使用virtualbox的教程。踩了网上的坑后&#xff0c;决定写一篇文章介绍virtualbox虚拟机上网的流程。 需求 1. virtualbox虚拟机与宿主机…

Linux 文件 IO 管理(第四讲:软硬链接和动静态库)

Linux 文件 IO 管理&#xff08;第四讲&#xff1a;软硬链接和动静态库&#xff09; 软硬链接操作与现象软链接硬链接 解释软链接硬链接作用 动静态库初识静态库怎么做库&#xff08;开发角度&#xff09;怎么用库&#xff08;使用角度&#xff09;安装当前目录直接使用 动态库…

JavaWeb程序设计(第四版)习题参考答案

JavaWeb程序设计&#xff08;第四版&#xff09;习题参考答案 目录 模块1 习题参考答案 模块2 习题参考答案 模块3 习题参考答案 模块4 习题参考答案 模块5 习题参考答案 模块6 习题参考答案 模块7 习题参考答案 模块8 习题参考答案 模块1 习题参考答案 选择题 1 .A …

WaveletGPT:基于小波的多尺度表征增强大型语言模型训练效率

斯坦福大学的研究人员首次将小波理论应用于大型语言模型&#xff0c;提出了WaveletGPT&#xff0c;通过在Transformer解码器层中添加多尺度滤波器&#xff0c;加速了模型训练速度&#xff0c;并在文本、音频和音乐等多个领域取得了显著的性能提升。 论文介绍 大型语言模型 (L…

求和问题题解

减 sort拍后就A了 #include <bits/stdc.h> #include <cstring> using namespace std; typedef long long ll; ll n,a[400005],cnt0,b[400005]; bool cmp(long long x,long long y){return x>y; } int main () {cin>>n;for(int i1;i<n;i){cin>>…

查缺补漏----同步,异步,半同步,分离式通信

目录 1.同步通信&#xff08;同步定时方式&#xff09; 2.异步通信 3.半同步通信 4.分离式通信 1.同步通信&#xff08;同步定时方式&#xff09; 同步通信方式&#xff08;比如SPI&#xff09;&#xff0c;是把许多字符组成一个信息组&#xff0c;这样&#xff0c;字符可…

Springboot 整合 durid

文章目录 Springboot 整合 druiddruid的优势配置参数使用整合 Druid配置数据源配置参数绑定配置参数配置监控页面配置拦截器 Springboot 整合 druid druid的优势 可以很好的监控 DB 池连接 和 SQL 的执行情况可以给数据库密码加密可以很方便的编写JDBC插件 配置参数 使用 整…

数据结构之树(4)

摘要&#xff1a;本篇主要讲哈夫曼树、并查集、二叉排序树、平衡二叉树等&#xff0c;非常非常非常重要&#xff01;&#xff01;&#xff01; 一、哈夫曼树 基于霍夫曼树&#xff0c;利用霍夫曼编码进行通信可以大大提高信道利用率&#xff0c;缩短信息传输时间&#xff0c;…

Android2024.2.1升级错误

提示 Gradle 版本不兼容&#xff0c;升级后就报错了 。 1.gradle安装包镜像 distributionBaseGRADLE_USER_HOME distributionPathwrapper/dists //distributionUrlhttps\://services.gradle.org/distributions/gradle-8.5-bin.zip distributionUrlhttps://mirrors.cloud.tencen…

Koa2项目实战1(项目搭建)

前言 在正式开始之前&#xff0c;需要先知道用到的东西&#xff1a; koa&#xff1a;Koa 是一个基于 Node.js 的 Web 应用框架&#xff0c;非常适合开发API服务&#xff0c;可以与前端框架&#xff08;如 Vue.js、React.js&#xff09;结合使用&#xff0c;实现前后端分离的开…

第八篇:磁盘管理(1)

目录 6.1分区 6.1.1基本分区 6.1.1.1磁盘的相关知识 6.1.1.1.1基础知识 6.1.1.1.2命名 1.对于串口硬盘&#xff1a;/dev/sda、/dev/sdb、/dev/sdc......往后都是一个字母一个字母的累加 2.对于并口硬盘&#xff1a;/dev/hda其余相同 6.1.1.1.3磁盘的分区方式 方式1&am…

c++_ 多态

目录 一.多态 1.1多态(polymorphism)的概念 1.2实现多态还有两个必须重要条件&#xff1a; 1.3 重载 和 虚函数的重写/覆盖 和 隐藏 的比对 1.4 协变(了解) 1.5 析构函数的重写 1.6 override 和final关键字 二.纯虚函数和抽象类 三. 多态的原理 3.1虚函数表指针 3.…

黑马JavaWeb开发跟学(十一)SpringBootWeb案例

黑马JavaWeb开发跟学十一.SpringBootWeb案例 SpringBootWeb案例1. 新增员工1.1 需求1.2 接口文档1.3 思路分析1.4 功能开发1.5 功能测试1.6 前后端联调 2. 文件上传2.1 简介2.2 本地存储2.3 阿里云OSS2.3.1 准备2.3.2 入门2.3.3 集成 3. 修改员工3.1 查询回显3.1.1 接口文档3.1…

性能测试笔记2-总

安装路径&#xff1a;先装jdk,后装JMeter 安装JDK&#xff1a; 下载JDK – 安装JDK – 配置环境变量 – 验证 安装Jmeter&#xff1a; 下载Jmeter – 安装Jmeter – 配置环境变量 – 启动验证 注意点&#xff1a; 下载JDK时&#xff0c;注意电脑操作系统是32位/64位 下载…

力扣 简单 110.平衡二叉树

文章目录 题目介绍解法 题目介绍 解法 平衡二叉树:任意节点的左子树和右子树的高度之差的绝对值不超过 1 //利用递归方法自顶向下判断以每个节点为根节点的左右子树的最大深度是否大于1 class Solution {public boolean isBalanced(TreeNode root) {if(root null){return tr…

Uniapp API

1.uni.showToast 显示消息提示框 unishowToast({ obj参数 }) 2.uni.showLoading 显示 loading 提示框, 需主动调用 uni.hideLoading 才能关闭提示框。 3.uni.showModal 显示模态弹窗&#xff0c;可以只有一个确定按钮&#xff0c;也可以同时有确定和取消按钮。类似于一个A…

windows上安装python环境

前言 最近电脑重装了系统&#xff0c;需要重新安装python环境 &#xff0c;因此记录一下 1.下载 打开python官网下载&#xff0c;下载链接&#xff1a;https://www.python.org/downloads/windows/ 点击下载 &#xff0c;我这里使用64位操作系统(大部分电脑)&#xff0c;根据…

怎么查看网站是否被谷歌收录,查看网站是否被谷歌收录的简便方法

查看网站是否被谷歌收录&#xff0c;有多种简便方法可供选择。以下是一些常用的简便方法&#xff1a; 一、使用“site:”指令 打开谷歌搜索引擎&#xff1a; 在浏览器中打开Google.com&#xff0c;确保使用的是谷歌的官方搜索引擎。 输入查询指令&#xff1a; 在搜索框中输…

网关路由登录校验

网关过滤器 登录校验必须在请求转发到微服务之前做&#xff0c;否则就失去了意义。而网关的请求转发是Gateway内部代码实现的&#xff0c;要想在请求转发之前做登录校验&#xff0c;就必须了解Gateway内部工作的基本原理。 暂时无法在飞书文档外展示此内容 如图所示&#xff…