一、整体链路图先看全貌浏览器 │ │ ① HTTP请求GET /ba/babgtadjust/123 ▼ TomcatNIO/Connector │ │ ② 请求进来找到对应 Servlet ▼ Spring MVCDispatcherServlet │ │ ③ 找到对应的 Controller 方法 ▼ Controller你的代码 │ │ ④ 调用 Service 层 ▼ Service业务逻辑 │ │ ⑤ 调用 MapperDAO ▼ MyBatisMapper → SQL │ │ ⑥ 执行 SQL操作数据库 ▼ 数据库MySQL │ │ ⑦ 返回结果一路向上 ▼ 浏览器收到 JSON 响应下面一步步拆开讲。二、第①步HTTP 请求怎么发出去的浏览器地址栏敲http://localhost:8080/ba/babgtadjust/123浏览器底层做的事1. DNS 解析 localhost → 127.0.0.1 2. 三次握手建立 TCP 连接端口 8080 3. 构造 HTTP 请求报文 ┌─────────────────────────────────┐ │ GET /ba/babgtadjust/123 HTTP/1.1│ │ Host: localhost:8080 │ │ Accept: application/json │ │ Cookie: JSESSIONIDxxxx │ └─────────────────────────────────┘ 4. 发送到 Tomcat三、第②步Tomcat 怎么接手Tomcat 里有Connector组件专门监听端口接收请求ConnectorNIO │ ├── 接收请求 ├── 解析 HTTP 报文请求行、Header、Body └── 构造 Request 对象HttpServletRequest │ ▼ Request 交给 Servlet 处理Tomcat 里配置了 Servlet 映射!-- web.xml --servletservlet-namedispatcher/servlet-nameservlet-classorg.springframework.web.servlet.DispatcherServlet/servlet-class/servletservlet-mappingservlet-namedispatcher/servlet-nameurl-pattern//url-pattern!-- 拦截所有请求 --/servlet-mapping所有请求都先到DispatcherServlet这一步叫前端控制器模式。四、第③步DispatcherServlet 内部干了什么核心这是 Spring MVC 的心脏一共有 9 个步骤DispatcherServlet.doDispatch() │ ├── 第1步HandlerMapping 找 Controller │ ↓ │ 根据 URL 找到对应的方法 │ 例如/ba/babgtadjust/{id} → BaBgtAdjustController.getById() │ ├── 第2步HandlerAdapter 判断适配器类型 │ ↓ │ 是用 RequestMappingHandlerAdapter最常见 │ ├── 第3步HandlerInterceptor.preHandle() 预处理 │ ↓ │ 拦截器链的 preHandle 一个个执行 │ 返回 false 则请求终止 │ ├── 第4步参数绑定最重要 │ ↓ │ PathVariable、RequestParam、RequestBody 等 │ 全部在这一步处理 │ ├── 第5步执行 Controller 方法 │ ↓ │ controller.getById(id) 被调用 │ ├── 第6步HandlerInterceptor.postHandle() 后处理 │ ↓ │ 拦截器链的 postHandle 一个个执行 │ ├── 第7步ViewResolver 处理视图如果有 │ ↓ │ return forward:/xxx 或 return redirect:/xxx │ 你的项目用 RestController不走视图 │ ├── 第8步异常处理ExceptionHandler │ ↓ │ 异常在这里被捕获返回统一格式 │ └── 第9步渲染 响应 ↓ 把结果写回 HTTP 响应浏览器收到 JSON五、第④步参数绑定背后发生了什么DispatcherServlet │ └── HandlerMethodArgumentResolver 一个个尝试 │ ├── PathVariable → PathVariableMethodArgumentResolver 处理 │ 从 URL 中提取 {billId} 部分 │ ├── RequestParam → RequestParamMethodArgumentResolver 处理 │ 从 QueryString 或 Body 中提取 │ └── RequestBody → RequestResponseBodyMethodProcessor 处理 用 Jackson 把 JSON 转成 Java 对象六、第⑤步你的 Controller 怎么被调用的Spring 会在启动时扫描所有RestController把方法注册到HandlerMapping// Spring 启动时内部做的事简化版HandlerMappingmappingrequestPath-{if(path.equals(/bt/vill/{billId})){returnnewHandlerMethod(btController,// 对象实例BtController.class,// 类getById,// 方法名MethodUtils.getMethod(...),// 反射拿到方法annotations// 方法上的注解);}returnnull;};调用时用反射MethodmethodBaBgtAdjustController.class.getMethod(getById,String.class);Objectresultmethod.invoke(controller,12345);// 反射调用七、第⑥步响应是怎么返回的你的 Controller 返回PostMapping(/save)publicResultVoidsave(RequestBodyBillbill){service.save(bill);returnResult.ok();// 返回 Result 对象}Spring MVC 找到对应的HandlerMethodReturnValueHandler你的 return Result.ok() │ └── ResultMethodReturnValueHandler 处理 │ └── 用 Jackson 把 Result 对象序列化成 JSON │ └── 写入 HttpServletResponse │ └── 浏览器收到 HTTP/1.1 200 OK Content-Type: application/json {code: 200, msg: success, data: null}八、第⑦步异常处理链假设你的 Service 抛了个异常// BgtEduReleaseServiceImpl.javathrownewBizException(额度不足);异常怎么被捕获的Service 抛异常 │ ↓ DispatcherServlet 捕获 │ ↓ ExceptionHandler 一个个匹配 │ ├── BizException → 对应的 ExceptionHandler 处理 ├── NullPointerException → 另一个 handler └── 其他 Exception → 最后兜底的 handler │ ↓ Result.error(...) 转成统一格式 │ ↓ 返回给浏览器