跟课做苍穹外卖Day1,最消耗耐心的时间点往往不是写代码,而是浏览器里那个登录页面死活进不去。界面明明出来了,输入账号密码点击登录,要么按钮转圈半天没反应,要么直接弹个报错,更气人的是偶尔啥也不发生,像网页被冻住了。我在很多学习交流群里看到过一模一样的问题,而绝大多数人的第一反应是关掉所有窗口重新启动,再不行就清缓存、换浏览器,折腾一圈依旧原地踏步。
其实“登录进不去”这件事,套路非常固定。只要你不慌,把登录请求从浏览器一路走到数据库的每一个环节拆开看,几分钟内就能定位到具体是哪一段断了。这篇文章就以苍穹外卖Day1为例,把我在实际排查中遇到过的高频原因、判断方法和修复步骤完整写出来,希望帮你少走点弯路。
1. 先别急着重启:把“登录进不去”拆成两类现象再动手
很多人一卡住就到处乱点,这是最浪费时间的地方。登录进不去这个描述太笼统了,至少要先把现象拆成两类,因为它们的排查路径完全不同,搞混了会白白消耗精力。
1.1 现象一:网页打不开、白屏或显示“无法访问此网站”
这类问题通常表现在浏览器地址栏会出现类似ERR_CONNECTION_REFUSED、ERR_CONNECTION_TIMED_OUT的错误提示,或者页面拿到一块空白。注意,这个阶段你连前端页面本身都没有真正访问到,问题大概率出在前端启动环节,而不是登录逻辑。
常见原因包括:前端项目没启动成功就急着打开浏览器;启动命令执行完但控制台还在报错,端口根本没监听;或者你打开了浏览器但访问的端口号跟开发服务器实际监听的不一致。比如有人用 Vite 做前端,项目里配置的是5173端口,结果手滑访问了8080,那看到的自然是拒绝连接。
1.2 现象二:页面正常显示,但一点登录就报错或没反应
这类才是真正需要查登录链路的。页面能出来,说明前端开发服务器是好的,问题大概率出现在“浏览器到后端接口”这个中间路段,或者“后端接口到数据库/缓存”这一段。常见的表现有点击登录后提示“请求失败”、F12 控制台报404 Not Found、500 Internal Server Error,或者干脆按钮一直在加载状态。
很多初学者面对第二种现象会去看前端代码,反复检查按钮事件、Axios 封装,最后发现代码根本没毛病。方向错了,当然找不到问题。
1.3 把登录请求想成一条送货链路
为了不绕弯,你可以把登录过程想象成一条送货链路:浏览器下发订单(请求登录)→ 前端开发服务器转发(Proxy)→ 后端接口接收 → Service 层校验 → 数据库(MySQL)查用户账号 → 缓存(Redis)保存登录状态 → 返回结果给浏览器。任何一环掉了链子,最终表象都是“登录进不去”。
接下来的每个章节,就是沿着这条链路逐段排查。你不用一次性看完所有章节,先定位自己的现象属于哪一类,然后精准跳转到对应部分就行。
2. 第一个高频元凶:后端服务根本没起来,或端口跟前端对不上
Day1 的新手最容易踩的坑,不是代码逻辑,而是服务启动流程不完整。我见过很多人只启动了前端,后端控制台早就红字一片退出了,但浏览器页面还能打开,于是误以为“环境没问题”,结果实际上是后端在裸奔。
2.1 先在日志里确认后端是真的活着
启动后端项目后,不要急着切回浏览器。先看启动日志,等出现类似“Started Application in x.xxx seconds”或“Tomcat started on port(s): 8080”这样的字样,并且没有红色异常堆栈,才说明后端真正起来了。
如果后端启动失败,常见的原因包括依赖没下载完整、端口被占用、配置文件读取不到等。你可以做一次最朴素的验证:在浏览器新标签页直接访问后端地址。假设项目配置端口是8080,登录接口路径是/api/user/login,那就访问http://localhost:8080/api/user/login。正常情况下即便返回错误 JSON,也说明后端在响应;如果浏览器直接显示“无法访问此网站”,那后端就是没起来。
2.2 端口对不上:前端代理指向 8081,后端跑在 8080
另一个高发问题,是前端代理配置里的目标端口和后端实际端口不一致。比如某同学的苍穹外卖项目中,后端跑在8080,但前端 Vite 代理配置写成了8081;或者反过来,后端换了端口但前端没改。最后结果就是浏览器请求送到一个没有服务的端口,什么响应都拿不到。
验证方法很简单,Windows 下在项目环境里执行命令查看端口占用:
netstat -ano | findstr 8080Linux 或 macOS 环境用:
lsof -i:8080如果端口列表里根本没有对应进程,那说明后端没监听这个端口。再看一下前端代理目标地址和后端实际运行端口是否一致,通常把它们统一成8080就解决了。
2.3 前端代理配置长什么样
以 Vite 为例,常见的前端代理配置长这样:
server: { port: 5173, proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true } } }这段配置的意思是:凡是以/api开头的浏览器请求,前端开发服务器会转发给http://localhost:8080。如果这里的target写错了端口,或者后端根本没开在8080,登录请求自然进不了后端大门。
这里有个很关键的细节:修改完前端代理配置后,必须重启前端开发服务器。很多人改了配置文件不重启,理所当然觉得刷新浏览器就行,结果配置根本没生效,白白多浪费十几分钟。
2.4 一个省时间的启动顺序习惯
我自己的习惯是,启动顺序严格固定:先启动 MySQL 和 Redis,再启动后端,最后启动前端。每次启动完扫一眼三个窗口的日志,后端确认没有异常堆栈,前端确认出现Local: http://localhost:5173/这样的输出,然后再打开浏览器。这套顺序看起来古板,但能帮你把“服务是否就绪”这件事变得非常清楚,排查问题时能直接排除一大半干扰项。
3. 浏览器里看到404或502:十有八九是前端代理没把请求送对
页面开得起来,后端也确认活着了,但点击登录依然失败。这时候打开浏览器的开发者工具(F12),切到 Network 面板,重新点一次登录,看接口请求发生了什么。这一眼,通常就能定下调子。
3.1 别凭感觉猜,先看请求到底出没出去
新手最容易跳过这一步,直接去翻后端代码。但后端代码翻一晚上,不如 F12 看一眼有效。打开 Network 后,勾选 Fetch/XHR 筛选类型,这样能看到比较干净的接口请求列表。如果点击登录之后 Network 面板里根本没有出现新的请求,那说明前端按钮事件可能有问题,比如表单验证没通过、按钮没有绑定提交逻辑、或者 Axios 请求地址为空。
如果出现了请求,但状态码是红字的404或502,那就是前端请求到了某个地方,但那个地方不认这条请求线索。404 常见意思是“请求路径找不到”,502 常见意思是“上游服务连不上或响应异常”。在这个场景里,二者都说明前端代理和目标后端之间没有对齐。
3.2 404 通常是路径前缀不一致
苍穹外卖这类项目里,前端封装请求时一般会在基础 URL 里带上/api,后端 Controller 的 RequestMapping 可能是/user/login或/api/user/login。如果前端请求发的是/api/user/login,而后端接口实际只挂在/user/login下,代理又把/api前缀原样传给了后端,后端自然找不到对应接口,返回 404。
判断办法很简单:F12 Network 里点击那条失败请求,看 Request URL 是什么,再对比后端 Controller 上的 RequestMapping 注解。如果发现前后缀不匹配,要么改后端接口路径,要么改前端请求基础路径。注意改完后端接口路径要重新编译启动,改完前端代理要重启前端。
3.3 502 通常是代理目标配错或后端还没就绪
如果 F12 里看到的是 502 Bad Gateway,那对应后端服务可能压根没起来,或者代理target指向了错误地址、错误端口。后端一旦挂掉或根本没启动,代理把请求转过去后拿不到任何响应,就会表现为 502。这个时候去后端控制台看一眼,如果进程已经退出了,先解决后端启动问题,502 自然消失。
我整理了一张对应关系表,适合排查时对照:
| F12 状态码 | 大概率原因 | 排查方向 |
|---|---|---|
| 404 | 请求路径与后端接口路径不一致 | 对比 Request URL 和 Controller 注解 |
| 502 | 代理 target 地址/端口错误,或后端未启动 | 检查 target 配置,确认后端端口 |
| 500 | 后端接口能收到,但内部执行出错 | 看后端控制台异常堆栈 |
| 无请求 | 按钮事件或请求封装有问题 | 检查前端表单提交逻辑、Axios baseURL |
3.4 一个容易忽略的小细节:请求头跨域被拦截
如果你没走前端代理,而是直接让前端代码请求后端地址,可能会出现跨域问题。浏览器控制台会报类似“Access to XMLHttpRequest has been blocked by CORS policy”的错误,表现同样是登录进不去。这种问题的本质是浏览器出于同源策略拦住了响应,跟代码逻辑无关。
最省事的方案是统一走前端代理,不要跨域;如果实在要跨域,就再后端配置一个 CORS 过滤器,允许指定来源访问。不过初学者建议优先用代理,少碰跨域配置,减少变量。
4. 接口报500的突破口:MySQL连不上和Redis没启动怎么查
如果 F12 里看到的不是 404 也不是 502,而是服务器内部错误 500,恭喜你,请求后端是收到并开始处理了,但后端在执行过程中炸了。这时候重点从浏览器转移到后端控制台,日志信息才是判案的关键。
4.1 后端日志里的异常堆栈是答案
点登录按钮,然后立刻切到后端控制台。你会看到一长串异常堆栈,不要被吓到,真正有用的线索往往在最前面的几行和最后的几行。比如Communications link failure、Access denied for user、Unknown database、Connection refused之类的关键字,直接点名了问题所在。
很多初学者看到一大片红色日志就慌了,其实只需要抓关键名词就好。英文不好没关系,用翻译软件查一遍关键字,通常就能明白问题出在谁身上。这里强调一个习惯:排查 500 时,不要来回刷新前端页面,而是反复点登录,让后端多刷几条日志出来,方便对比。
4.2 MySQL 连不上是 Day1 的重灾区
苍穹外卖这类项目登录用户信息都存 MySQL,后端启动或请求登录时会去连数据库。常见报错和对应解法如下:
| 报错关键字 | 原因 | 处理办法 |
|---|---|---|
Access denied for user 'root'@'localhost' | 数据库账号或密码错误 | 检查后端配置里的 username/password |
Unknown database 'xxx' | 数据库没创建,或配置里的库名不对 | 在 MySQL 中执行建库语句,并核对库名 |
Communications link failure | 连不上 MySQL 服务,可能是没启动,或端口被改 | 确认 MySQL 进程在跑,端口是默认 3306 |
Public Key Retrieval is not allowed | MySQL 8 驱动加密方式导致 | 在连接 URL 后面加allowPublicKeyRetrieval=true |
以 Spring Boot 为例,后端配置文件里会有一段数据源配置,这是排查时首先检查的地方:
spring: datasource: url: jdbc:mysql://localhost:3306/sky_take_out?serverTimezone=Asia/Shanghai&characterEncoding=utf-8 username: root password: 123456如果这条连接串里的数据库名、用户名、密码有任何一项和本地 MySQL 实际环境对不上,后端就会抛异常。一个特别容易踩的坑是:本地 MySQL 设了密码,但配置文件里密码是空的;或者密码正确但端口不是 3306。这些都要一一核对。
4.3 Redis 没启动也会让登录卡住
苍穹外卖这类项目的登录流程里,Redis 通常用来缓存验证码、存储登录令牌或用户状态。如果后端启动时没有强制连接 Redis,可能当时不会报错,但登录时会去读写缓存,这时候如果 Redis 没启动,接口就会抛异常,表现为 500。
报错往往长这样:
java.net.ConnectException: Connection refused: localhost/127.0.0.1:6379意思是本机的 6379 端口没有服务在监听。处理方式很简单:把 Redis 服务启动起来。Windows 用户如果直接运行了redis-server.exe,要保证窗口不关闭;Linux 用户可以用systemctl start redis或在项目目录下用容器启动。确认 Redis 启动后,再点一次登录,这个问题基本就消失。
4.4 后端启动时并非所有连接都会立刻建立
这里要特别说明一个反直觉的点:即使 MySQL 或 Redis 没启动,后端有时也能正常启动。因为数据源连接通常懒加载,或者启动时只做少量检测,真正发生数据库访问动作才连。所以不要因为“后端明明起来了”就排除数据库和缓存问题,必须在登录报错后主动检查这两个依赖服务。
为了减少这种反复,我建议你在本地开发时养成一个习惯:每天开工先把 MySQL 和 Redis 起来,再启动后端。这种看似简单的优先级,能直接省掉一大段排查时间。
5. 验证码刷不出来和缓存捣乱:两个容易忽略的登录拦路虎
前面几条链路都排过了,有时候登录还是进不去,或者页面体验异常,问题可能出在“看起来不起眼”的地方。这里分享两个我在实测中经常遇到、但新手完全不往这想的场景。
5.1 验证码图片不显示,登录按钮跟着遭殃
部分版本的苍穹外卖项目里,登录页会加载验证码图片。如果验证码接口请求失败,图片位置就会空白,有些前端逻辑会在验证码未加载时把登录按钮置灰或直接拦截提交,看起来就像“登录进不去”。
验证码接口失败通常有两个原因:一是前端代理只配置了/api,而验证码接口路径可能是/api/code或/code,没被代理覆盖到;二是验证码生成过程依赖底层字体或图形库,后端运行环境缺了相关资源,导致生成验证码时抛异常。前者改代理配置,后者需要看后端日志确认具体缺什么,然后补齐对应依赖。
这里我想强调一个经验:看到登录按钮点了没反应,第一件事是看页面上的验证码图片是否正常。这个小动作我一天能提醒自己十遍,因为它太容易被忽略了。
5.2 浏览器缓存让旧配置“阴魂不散”
修改了前端代理配置或接口地址后,明明重启了前端,但浏览器里登录还是失败,这时候要怀疑浏览器把旧版 JavaScript 文件缓存住了。页面加载用的还是旧逻辑,请求当然还是发到旧地址、走旧代理。
解决方法很朴素:按Ctrl + Shift + R强制刷新页面,忽略缓存;或者直接开一个无痕窗口重新访问登录页。无痕窗口不会加载旧的缓存文件,是最干净的环境。很多“重启了好几次都进不去”的问题,一开无痕窗口就好了,原因就在这里。
建议你在做前端项目时,把“无痕窗口验证”当成一个默认动作。特别是改了前端配置、代理、请求路径之后,无痕窗口的结果才算数,用旧的带缓存页面反复测,只会干扰判断。
5.3 控制台报的红字不一定都是致命错误
做前端页面时,F12 Console 里会出现一些其他资源的报错,比如favicon.ico加载失败,或者某个静态资源 404。这些红字看着吓人,但不一定影响登录。很多初学者看到 Console 里红字就以为自己写错了,慌里慌张去删代码,结果越改越乱。
判断标准很简单:看 Network 里那条登录请求本身的状态。如果登录请求是成功的,或者至少正常发出了,那 Console 里的部分红字可能只是无关紧要的资源请求失败,可以暂时不管。如果登录请求本身报错了,才需要顺着它往下追。
6. 五分钟顺藤摸瓜:我整理的一套登录排查顺序
把前面所有常见问题汇总一下,我给自己总结了一套不管换哪个项目都能用的排查顺序。登录进不去的时候,按照这个步骤走一遍,大部分情况下五分钟内就能定位到问题,比无头苍蝇式重启高效得多。
6.1 五分钟排查法速查表
| 时间 | 动作 | 判断依据 |
|---|---|---|
| 第1分钟 | 看后端控制台 | 启动是否成功,有无异常堆栈 |
| 第2分钟 | 开浏览器 F12 Network | 登录请求状态码是什么,请求是否发出 |
| 第3分钟 | 直接 curl 后端接口 | 后端是否独立响应,排除前端干扰 |
| 第4分钟 | 检查 MySQL 和 Redis | 服务是否启动,配置是否匹配 |
| 第5分钟 | 开无痕窗口重新登录 | 排除浏览器缓存干扰 |
第 3 分钟的curl尤其好用,它能帮你把“后端问题”和“前端问题”干净地切开。假如你直接访问后端接口都能正常返回,那后端大概率没问题,重点回到前端;如果 curl 本身也报错,那后端或者依赖服务一定有状况。
curl http://localhost:8080/api/user/login看到返回结果后,不管是不是业务上的成功,只要后端有响应,就说明链路后半段是通的。
6.2 日志关键字对照表,快速定位章节
如果你没时间从头看,我整理了一份关键字对照,可以直接跳到对应章节:
| 日志或报错关键字 | 问题方向 | 参考章节 |
|---|---|---|
页面显示ERR_CONNECTION_REFUSED | 前端服务没起或端口错了 | 第1章、第2章 |
404 Not Found | 前端代理路径和后端接口对不上 | 第3章 |
502 Bad Gateway | 代理目标错误或后端未启动 | 第3章 |
Access denied/Unknown database | MySQL 连接配置问题 | 第4章 |
Connection refused: ...6379 | Redis 未启动或端口不对 | 第4章 |
| 验证码空白 | 代理未覆盖验证码路径或后端缺字体库 | 第5章 |
6.3 整个过程里最值钱的能力:克制住“乱试”的冲动
很多人一遇到问题就想把所有配置随便改一遍,比如把端口从 8080 改成 8081、把密码重设一下、把代理路径乱删一通。结果经常是本来只有一个问题,改完多了两个新问题,最后自己都解释不清系统处于什么状态。
我的切身体会是,排查登录这一类服务连通性问题,最需要的是定力。明确每一步在验证什么,改一个变量,重新测一次,记录结果,再改下一个。比如先确认后端端口通,再确认数据库连得上,然后才是前端代理配置。每一步都只解决一个变量,问题没有变大之前,你永远都知道自己在哪一环节。
苍穹外卖 Day1 的登录失败,绝大多数逃不出上面这些原因。等你把这条链路熟到闭着眼都能背出来,后面再做订单、商品、店铺那些功能时,你会发现排查思路都是同样的套路,只是换了个接口路径而已。把这份经验存下来,遇到问题按顺序过一遍,比自己闷头折腾一个小时划算得多。