1. SpringBoot请求处理全链路概述当你用浏览器访问一个SpringBoot应用的URL时这个请求会经历一场奇妙的旅行。想象一下快递包裹从发货到签收的过程包裹要经过分拣中心、运输车、配送站等多个环节每个环节都有特定的处理逻辑。SpringBoot处理请求的流程也类似从Tomcat容器接收请求开始到最终返回响应中间会经过过滤器、拦截器、参数绑定、控制器方法执行等多个关键节点。我刚开始用SpringBoot时经常搞不清楚过滤器和拦截器的区别也不明白为什么有些异常能被ControllerAdvice捕获而有些不能。后来通过阅读源码和实际踩坑终于理清了整个流程。下面我就用最直白的语言带你走一遍这个完整链路。2. 请求处理全流程详解2.1 Tomcat容器接收请求当请求到达服务器时Tomcat作为Servlet容器最先接手。它会把HTTP请求解析成HttpServletRequest对象然后创建对应的HttpServletResponse对象。这个过程就像快递公司收到包裹后先检查外包装是否完好然后登记发货人和收货人信息。Tomcat会维护一个线程池来处理并发请求每个请求都会分配一个独立线程。这里有个性能优化点合理配置Tomcat的线程池参数比如maxThreads、acceptCount等可以显著提高并发处理能力。我在实际项目中就遇到过因为线程池配置不当导致的请求堆积问题。2.2 Filter过滤器链处理Tomcat接下来会把请求交给Filter链处理。Filter是JavaEE标准不依赖Spring主要用于处理通用的横切关注点比如字符编码设置跨域请求处理XSS防护权限校验请求日志记录Filter的执行顺序由Order注解或FilterRegistrationBean的order属性决定数值越小优先级越高。常见的坑是忘记调用chain.doFilter()导致请求中断我就犯过这个错误调试了半天才发现问题。// 典型Filter实现示例 public class LogFilter implements Filter { Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { long start System.currentTimeMillis(); // 前置处理相当于快递分拣 System.out.println(请求开始 ((HttpServletRequest)request).getRequestURI()); chain.doFilter(request, response); // 放行到下一个Filter // 后置处理相当于快递签收后的回执 System.out.println(请求耗时 (System.currentTimeMillis()-start) ms); } }2.3 DispatcherServlet分发请求经过所有Filter后请求来到Spring的核心入口DispatcherServlet。它就像公司的前台负责把不同类型的请求分发给对应的部门Controller。DispatcherServlet的工作流程根据请求URL查找对应的Handler控制器方法获取适合的HandlerAdapter默认是RequestMappingHandlerAdapter执行拦截器链的preHandle方法真正调用控制器方法处理返回结果JSON、视图等执行拦截器链的postHandle方法处理异常如果有执行拦截器链的afterCompletion方法2.4 Interceptor拦截器链Interceptor是SpringMVC的概念比Filter更接近业务逻辑。典型应用场景包括登录状态验证权限检查接口耗时统计防重复提交拦截器有三个关键方法public class AuthInterceptor implements HandlerInterceptor { // 控制器方法执行前调用 Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { // 验证token逻辑 return true; // 返回false会中断请求 } // 控制器方法执行后调用异常时不执行 Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) { // 可以修改返回的ModelAndView } // 请求完成后调用始终执行 Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { // 资源清理等收尾工作 } }2.5 参数绑定与方法执行Spring会通过HandlerMethodArgumentResolver机制将请求参数绑定到方法参数上包括RequestParam查询参数PathVariable路径变量RequestBodyJSON/XML请求体ModelAttribute表单数据RequestHeader请求头这里常见的坑是参数类型转换失败比如前端传abc到Integer参数。可以通过自定义Converter或实现WebMvcConfigurer#addFormatters来扩展类型转换。2.6 返回值处理控制器方法执行完后返回值会通过HandlerMethodReturnValueHandler处理ResponseBody使用HttpMessageConverter转换如JacksonModelAndView视图渲染String视图名void根据请求URL自动找视图我曾经遇到一个坑返回的JSON字段名突然变成了驼峰转下划线后来发现是配置了错误的Jackson PropertyNamingStrategy。2.7 异常处理Spring的异常处理流程先找ExceptionHandler当前Controller内再找ControllerAdvice中的ExceptionHandler最后用默认的BasicErrorController需要注意的是Filter中抛出的异常不会被ControllerAdvice捕获拦截器afterCompletion抛出的异常只会记录日志想要全局处理Filter异常可以自定义ErrorController3. 关键组件对比与最佳实践3.1 Filter vs Interceptor特性FilterInterceptor作用范围Servlet容器级别SpringMVC级别依赖Servlet APISpring框架执行顺序最先执行在DispatcherServlet之后获取Bean不能直接注入可以自动注入使用场景通用预处理/后处理业务相关处理实际项目中我通常这样分工Filter处理跨域、编码、XSS防护、全局日志Interceptor处理权限校验、接口限流、业务日志3.2 常见问题解决方案全局异常处理失效问题Filter异常在第一个Filter中try-catch或者实现ErrorController拦截器afterCompletion异常只能记录日志无法阻止响应返回多个ControllerAdvice用Order控制顺序性能优化建议在Filter层做请求限流使用ControllerAdvice统一包装响应复杂参数绑定实现自定义Converter静态资源映射不要走SpringMVC流程调试技巧在application.properties中添加logging.level.org.springframework.webDEBUG logging.level.org.springframework.boot.autoconfigureDEBUG使用SpringBoot Actuator的httptrace端点自定义Filter和Interceptor时添加详细日志4. 实战自定义全链路日志最后分享一个我在生产环境使用的全链路日志方案// 1. 定义TraceID过滤器 public class TraceFilter implements Filter { Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { String traceId UUID.randomUUID().toString(); MDC.put(traceId, traceId); // 用于日志追踪 ((HttpServletResponse)response).setHeader(X-Trace-ID, traceId); chain.doFilter(request, response); MDC.remove(traceId); } } // 2. 定义日志拦截器 public class LogInterceptor implements HandlerInterceptor { private static final Logger log LoggerFactory.getLogger(LogInterceptor.class); Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { log.info(请求开始 {} {}, request.getMethod(), request.getRequestURI()); request.setAttribute(startTime, System.currentTimeMillis()); return true; } Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { long cost System.currentTimeMillis() - (long)request.getAttribute(startTime); log.info(请求完成 状态码{} 耗时{}ms, response.getStatus(), cost); } } // 3. 注册组件 Configuration public class WebConfig implements WebMvcConfigurer { Bean public FilterRegistrationBeanTraceFilter traceFilter() { FilterRegistrationBeanTraceFilter bean new FilterRegistrationBean(); bean.setFilter(new TraceFilter()); bean.setOrder(Ordered.HIGHEST_PRECEDENCE); return bean; } Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LogInterceptor()) .addPathPatterns(/**); } }这个方案可以清晰看到每个请求的完整生命周期配合ELK等日志系统能快速定位问题。特别是在微服务架构下通过TraceID可以串联起跨服务的调用链。