完全理解你的感受!这个链路确实非常长,从前端到后端数据库,中间夹杂了网络层、Web 容器层(Tomcat)和框架层(Spring)的大量组件。很多概念(比如过滤器和拦截器)不仅名字像,作用看起来也很像,很容易让人觉得“乱成一锅粥”。

别慌,我们现在就把这锅粥理成一条高度清晰的“安检流水线”。

我们可以把整个请求的过程分为四个大阶段:外围网络层 ➡️ Tomcat 容器层 ➡️ Servlet 规范层 ➡️ Spring MVC 框架层


第一阶段:外围网络层(请求的漫长旅途)

当用户在前端(浏览器/App)点击按钮,发出一个 HTTP 请求(例如 GET /api/user),请求首先要在广阔的网络世界里找到你的服务。

  1. 前端 (Frontend): 构造 HTTP 请求报文,通过 TCP/IP 网络发出去。
  2. Nginx (反向代理/负载均衡): 请求通常第一个到达的是 Nginx。
  • 它的角色: 公司的“大门保安兼引路人”。它负责把静态资源(图片、前端 HTML)直接返回,如果是 API 请求,它会根据负载均衡算法,把请求分发给背后的多个网关节点。
  1. 网关 (API Gateway, 如 Spring Cloud Gateway):
  • 它的角色: 微服务集群的“总调度中心”。在这里通常会做全局的身份认证(校验 Token)、限流(防止恶意刷接口)、以及路由转发。验证通过后,网关会将请求转发给具体的微服务实例(也就是你的 Spring Boot 应用)。

第二阶段:进入 Tomcat (服务器的内部调度)

你的 Spring Boot 应用内嵌了一个 Tomcat。当请求到达这个微服务时,其实是先交给了 Tomcat 处理。Tomcat 的核心架构分为两部分:Connector(连接器)Container(容器)

  1. Connector (网络接待员):
  • Acceptor: 接收网关发来的 TCP 连接。
  • Poller: 监听这些连接上的 I/O 事件(数据是否可读)。
  • Worker Threads (工作线程池): 一旦有请求数据,Poller 会把它交给 Tomcat 线程池中的一个 Worker 线程。在这个阶段,原始的网络字节流被解析成了 Java 对象:HttpServletRequestHttpServletResponse
  1. Container (处理车间):
  • 请求被层层传递:Engine (引擎) ➡️ Host (虚拟主机) ➡️ Context (你的应用上下文) ➡️ Wrapper (包装具体的 Servlet)。
  • Tomcat 最终要把这个请求交给 Spring MVC 的核心——DispatcherServlet,但在交接之前,必须先经过“过滤器”。

第三阶段:Servlet 规范层(Filter 过滤器)

在请求真正进入 Spring 框架之前,它还在 Tomcat 的管辖范围内。此时,它必须穿过一条 FilterChain(过滤器链)

  • 前处理: Filter.doFilter() 方法的前半部分。在这里,我们通常做一些最基础、最通用的工作。例如:全局的跨域处理 (CORS)、字符编码转换、XSS 防护等。
  • 放行: 调用 chain.doFilter(request, response),把请求传递给下一个过滤器,或者最终传给 Servlet。
  • 后处理: 等后端的业务执行完,响应返回时,会沿着过滤器链反向穿过 doFilter() 的后半部分。

第四阶段:Spring MVC 框架层(请求的最终目的地)

穿过过滤器后,请求终于离开了纯 Tomcat 的世界,进入了 Spring MVC 的领地。这里的核心是 DispatcherServlet(前端控制器),它像一个项目经理,负责协调所有工作。

  1. 找人 (HandlerMapping): DispatcherServlet 拿到请求后,去问 HandlerMapping(处理器映射器):“谁能处理 /api/user 这个路径?”。它会返回一个 执行链 (HandlerExecutionChain),里面包含了你的 Controller 方法以及配置好的Interceptor(拦截器)
  2. 拦截器前处理 (preHandle):
  • 在真正调用你的 Controller 之前,先执行拦截器的 preHandle()
  • 作用: 检查更细粒度的业务逻辑。比如:用户是否有权限访问这个特定的接口?如果没有,直接 return false,请求打回。
  1. 参数适配与执行 (HandlerAdapter & Controller):
  • HandlerAdapter 负责把 HTTP 里面的 JSON 数据,转换成你 Controller 方法上的 @RequestBody 对象(通过 HttpMessageConverter)。
  • 执行业务: 你的 Controller 被调用,调用 Service ➡️ DAO,查数据库,最后返回结果。
  1. 拦截器后处理 (postHandle):
  • Controller 执行完,但在返回结果给前端(或渲染视图)之前执行。现代前后端分离项目(全 JSON 交互)中,这个方法用得相对较少了。
  1. 异常与视图处理:
  • 如果有异常,会被 @ExceptionHandler 捕获处理。如果是正常数据,则转换回 JSON 写入 HttpServletResponse
  1. 拦截器最终完成 (afterCompletion):
  • 无论成功还是抛出异常,整个请求处理完毕后都会执行。非常适合用来清理 ThreadLocal 数据,防止内存泄漏,或者记录操作日志。

💡 核心答疑:Filter(过滤器) vs Interceptor(拦截器)

这也是最容易让你觉得“乱”的地方,我用一张表帮你对比清楚:

特性 Filter (过滤器) Interceptor (拦截器)
归属权 Servlet 规范(Tomcat 管理) Spring 框架(Spring 管理)
拦截范围 几乎所有请求(包括静态资源、CSS、JS) 只有进入 Spring MVC 的请求(即你的 Controller)
颗粒度/上下文 只能拿到 requestresponse 可以拿到目标调用的 Method@Annotation 等详细信息
执行顺序 在 Interceptor 外围(先入后出) 在 Filter 内部(紧贴 Controller)

总结一下整个请求的心跳轨迹(洋葱模型):
浏览器 ➡️ Nginx ➡️ 网关 ➡️ Tomcat(Connector->Container) ➡️ Filter ➡️ DispatcherServlet ➡️ Interceptor ➡️ Controller(业务代码)
处理完后,再按原路层层返回。

看完这条“安检流水线”,你现在感觉思路清晰一些了吗?在这个全流程中,你平时开发中最常在哪一层写代码(比如是网关、拦截器还是 Controller)?或者哪一层的配置最让你头疼,我们可以针对性地深入聊聊。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐