系列:后端路线 · 收官篇
前面四篇 + 一个完整示例,你已经能写出来。但”写得出来”和”跑得通”之间,隔着一堆坑。本篇按”从外到内”的排查顺序,把最高频的问题与对应解法列给你。

1. 排查总原则:由外到内,逐层缩小

1
网络/防火墙 → 服务是否在跑 → 路由(404) → 参数(400) → 业务/数据库(500) → 数据正确与否

不要一上来就改代码。先确认”请求到底有没有到应用”,再往里查。

2. 连不上 / 超时(请求根本没反应)

现象 可能原因 排查/解决
Connection refused 服务没启动 / 端口错 ps -ef|grep java 看进程;确认 server.port
云上访问不了 安全组未放行端口 云控制台放行 8080/对应端口
Could not connect to MySQL 数据库地址/账号错、MySQL 未起、防火墙拦 3306 本地 mysql -u root -p 试连;检查 urlserverTimezone
本地能连、服务器不能连 DB 数据库只允许 localhost bind-address 或授权远程用户

排查顺序:先 ping/telnet ip port 测网络连通,再查服务进程,再看日志。

3. 404 Not Found(路由没匹配)

  • @RequestMapping 路径写错 / 少了前缀。
  • Controller 没被扫描到:启动类所在包的子包才被扫到(默认 @ComponentScan 只扫启动类同包及子包)。解决:把 controller 放启动类包下,或显式 @ComponentScan("com.xxx")
  • 用了 @Controller 却期望返回 JSON(应是 @RestController)。

4. 400 Bad Request(参数问题)

  • 前端发 JSON,后端用 @RequestParam 接 → 改用 @RequestBody
  • 字段类型不匹配(字符串传数字、日期格式错)。
  • 必填字段缺失。用 @Valid + @NotBlank 等做校验,并全局异常处理返回清晰错误。

5. 500 Internal Error(服务端炸了)

第一步永远看日志 stack tracetail -f app.log),定位异常类型与行号:

  • NullPointerException:对象未注入/未初始化(@Autowired 失败、字段没 set)。
  • SQLException:SQL 语法错 / 字段名错 / 表不存在。
  • DuplicateKeyException:唯一索引冲突(用户名重复,应业务层先查或捕获)。
  • Transaction rolled back:事务内抛异常被回滚,看根因异常。

绝不要”盲改代码”。异常信息 + 行号基本能直接定位。

6. 中文乱码

  • 数据库 / 表 / 连接都要 utf8mb4:建表 CHARSET=utf8mb4,连接串 characterEncoding=utf8mb4
  • 响应乱码:produces = "application/json;charset=utf-8" 或全局配置 spring.http.encoding.charset=utf-8
  • 文件/IDE 编码统一 UTF-8。

7. 事务不生效(@Transactional 没回滚)

原因 说明
同类方法互相调用 this.methodB() 不走代理,事务失效;需注入自己或拆到另一类
异常被 catch 吞掉 抛出的异常没往外冒,事务感知不到 → 必须 rethrow 或 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()
抛的是受检异常/自定义异常 默认只回滚 RuntimeException;用 @Transactional(rollbackFor = Exception.class)
方法非 public Spring 事务基于代理,private/protected 不生效
数据库引擎非 InnoDB MyISAM 不支持事务

8. 慢查询 / 接口响应慢

  • 没加索引:用 EXPLAIN 看是否 type=ALL(全表扫);按查询条件建索引(复习 Part 1)。
  • N+1 查询:循环里查库(for 里 getById)→ 改成批量 IN 或联表。
  • 返回数据过大:分页 LIMIT 没用,一次查全表。
  • 连接池打满:并发高时 HikariCP 连接不够,调大 maximum-pool-size

9. 跨域 CORS 报错(浏览器红字)

Access-Control-Allow-Origin 缺失 → 后端加 CORS 配置(见 Part 4)。注意:预检 OPTIONS 也要放行;allowCredentials=trueallowedOriginPatterns 不能用 *,须指定具体域名。

10. 调试工具箱(必备)

工具 用途
curl 命令行发请求,排除前端干扰,验证接口本身
Postman / Apifox 图形化调试、保存集合、环境变量
tail -f app.log 实时看应用日志
IDEA 断点调试 逐行看变量值,定位逻辑错
EXPLAIN <sql> 分析 SQL 是否走索引
Spring Boot Actuator /actuator/health/metrics 看应用健康与指标
telnet ip port / ping 测网络连通

11. 调试心法(三条)

  1. 先复现,再改:不能稳定复现的 bug 不要急着改,先拿到稳定复现步骤。
  2. 缩小范围:注释掉一半逻辑、用最小请求复现,二分定位。
  3. 看证据,不猜:异常栈、HTTP 状态码、数据库实际数据,比”我觉得应该是…”可靠。

12. 自测 Checklist(上线前过一遍)

  • 接口用 curl/Postman 实测通过(不只靠前端)
  • 异常输入(空值、超长、错误类型)有合理响应,不 500
  • 关键查询已加索引,慢 SQL 已排查
  • 敏感配置(密码)走环境变量,未硬编码
  • 生产配置(profile=prod)生效,日志路径正确
  • 服务进程在后台常驻,重启可恢复
  • 跨域(如需)已正确配置

系列到此收官。你已走完:全链路概览 → MySQL → Spring Boot → API/HTTP → 部署 → 完整示例 → 调试
下一步可深入:Redis 缓存、RabbitMQ 消息队列、Spring Security/JWT 鉴权、MySQL 锁与执行计划、分库分表与读写分离、Docker/K8s 部署。每一块都可以在此基础上单独成篇。