Spring MVC 架构总览与请求处理流程
🧭Spring MVC 架构总览与请求处理流程
文章目录
- 🧭Spring MVC 架构总览与请求处理流程
- 🏗️ 一、Spring MVC 整体架构概览
- 💡 MVC 设计模式在 Spring 中的实现
- 🔧 核心组件职责说明
- 🔄 二、DispatcherServlet 初始化流程
- 🚀 DispatcherServlet 类层次结构
- ⚙️ 初始化源码深度解析
- 📊 初始化日志追踪
- 🌐 三、HTTP 请求处理完整执行链
- 🔄 请求处理时序图
- ⚡ doDispatch 方法源码解析
- 🔍 处理器执行链构建
- 🤝 四、核心组件协作机制
- 🎯 HandlerMapping 映射机制
- ⚡ HandlerAdapter 适配执行
- 🎨 ViewResolver 视图解析
- 📊 五、请求处理日志追踪
- 🔍 请求处理调试工具
- 📝 完整请求处理日志示例
- 🔧 调试配置启用
- 💡 六、性能优化与最佳实践
- ⚡ 组件配置优化
- 🚀 异步处理优化
- 🔍 性能监控端点
- 📊 优化效果对比
🏗️ 一、Spring MVC 整体架构概览
💡 MVC 设计模式在 Spring 中的实现
Spring MVC 核心架构图:
🔧 核心组件职责说明
Spring MVC 九大核心组件:
| 组件 | 职责说明 | 关键接口 / 核心类 | 补充说明 / 执行阶段 |
|---|---|---|---|
| DispatcherServlet | 前端控制器(Front Controller),统一接收所有请求并协调各组件 | org.springframework.web.servlet.DispatcherServlet | MVC 核心调度中心,负责请求分发、异常处理、视图渲染。 |
| HandlerMapping | 根据请求 URL 查找对应的 Controller 及处理方法 | HandlerMapping、RequestMappingHandlerMapping | 请求阶段第一个执行的组件,返回 HandlerExecutionChain。 |
| HandlerAdapter | 将 HandlerMapping 返回的处理器适配为可执行对象 | HandlerAdapter、RequestMappingHandlerAdapter | 执行真正的 Controller 方法(支持参数绑定、@RequestBody 等)。 |
| Controller | 承载核心业务逻辑的请求处理器 | @Controller / @RestController | 一般对应业务模块的入口层,处理请求并返回 Model 或 Response。 |
| HandlerInterceptor | 请求拦截与前后处理逻辑(如鉴权、日志、限流) | HandlerInterceptor | 可实现 preHandle、postHandle、afterCompletion 三个阶段。 |
| Model | 封装业务处理结果的模型数据容器 | Model / ModelMap / ModelAndView | 在 Controller 中组装数据,交由视图层展示。 |
| ViewResolver | 根据返回值解析对应视图(如 JSP、Thymeleaf、Freemarker) | ViewResolver、InternalResourceViewResolver | 将逻辑视图名解析为实际渲染视图对象。 |
| View | 负责将模型数据渲染为最终响应内容 | View、ThymeleafView、MappingJackson2JsonView | 支持多视图技术:HTML、JSON、PDF、Excel 等。 |
| ExceptionHandler | 捕获并处理控制器执行过程中的异常 | @ExceptionHandler、@ControllerAdvice | 统一异常处理机制,支持全局异常捕获与响应格式化。 |
🔄 二、DispatcherServlet 初始化流程
🚀 DispatcherServlet 类层次结构
DispatcherServlet 继承体系:
⚙️ 初始化源码深度解析
DispatcherServlet 初始化核心方法:
public class DispatcherServlet extends FrameworkServlet {/*** WebApplicationContext 刷新时的回调* 核心初始化入口*/@Overrideprotected void onRefresh(ApplicationContext context) {initStrategies(context);}/*** 初始化九大策略组件*/protected void initStrategies(ApplicationContext context) {// 1. 文件上传处理器initMultipartResolver(context);// 2. 本地化解析器initLocaleResolver(context);// 3. 主题解析器initThemeResolver(context);// 4. 处理器映射器(核心)initHandlerMappings(context);// 5. 处理器适配器(核心)initHandlerAdapters(context);// 6. 异常处理器initHandlerExceptionResolvers(context);// 7. 视图名解析器initRequestToViewNameTranslator(context);// 8. 视图解析器(核心)initViewResolvers(context);// 9. 闪存属性管理器initFlashMapManager(context);}
}
HandlerMapping 初始化详细流程:
private void initHandlerMappings(ApplicationContext context) {this.handlerMappings = null;// 1. 检测所有 HandlerMapping 类型的 Beanif (this.detectAllHandlerMappings) {Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);if (!matchingBeans.isEmpty()) {this.handlerMappings = new ArrayList<>(matchingBeans.values());// 排序:Ordered 接口或 @Order 注解AnnotationAwareOrderComparator.sort(this.handlerMappings);}} else {// 2. 按名称查找特定 Beantry {HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);this.handlerMappings = Collections.singletonList(hm);} catch (NoSuchBeanDefinitionException ex) {this.handlerMappings = null;}}// 3. 确保至少有一个默认的 HandlerMappingif (this.handlerMappings == null) {this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);}
}
📊 初始化日志追踪
初始化过程调试日志:
@Component
@Slf4j
public class DispatcherServletInitLogger implements ApplicationListener<ContextRefreshedEvent> {@Autowiredprivate DispatcherServlet dispatcherServlet;@Overridepublic void onApplicationEvent(ContextRefreshedEvent event) {log.info("=== DispatcherServlet 初始化报告 ===");// 反射获取组件信息try {logHandlerMappings();logHandlerAdapters();logViewResolvers();} catch (Exception e) {log.error("初始化日志记录失败", e);}}private void logHandlerMappings() throws Exception {Field handlerMappingsField = DispatcherServlet.class.getDeclaredField("handlerMappings");handlerMappingsField.setAccessible(true);@SuppressWarnings("unchecked")List<HandlerMapping> mappings = (List<HandlerMapping>) handlerMappingsField.get(dispatcherServlet);log.info("HandlerMappings ({}个):", mappings.size());for (HandlerMapping mapping : mappings) {log.info(" - {}: {}", mapping.getClass().getSimpleName(), getMappingDetails(mapping));}}private String getMappingDetails(HandlerMapping mapping) {if (mapping instanceof RequestMappingHandlerMapping) {return "注解控制器映射";} else if (mapping instanceof BeanNameUrlHandlerMapping) {return "Bean名称URL映射";} else if (mapping instanceof SimpleUrlHandlerMapping) {return "简单URL映射";}return "自定义映射";}
}
控制台输出示例:
2023-10-01 10:00:01.123 INFO - === DispatcherServlet 初始化报告 ===
2023-10-01 10:00:01.124 INFO - HandlerMappings (3个):
2023-10-01 10:00:01.125 INFO - - RequestMappingHandlerMapping: 注解控制器映射
2023-10-01 10:00:01.126 INFO - - BeanNameUrlHandlerMapping: Bean名称URL映射
2023-10-01 10:00:01.127 INFO - - SimpleUrlHandlerMapping: 简单URL映射
2023-10-01 10:00:01.128 INFO - HandlerAdapters (4个):
2023-10-01 10:00:01.129 INFO - - RequestMappingHandlerAdapter: 注解控制器适配器
🌐 三、HTTP 请求处理完整执行链
🔄 请求处理时序图
Spring MVC 请求处理完整流程:
⚡ doDispatch 方法源码解析
DispatcherServlet 核心分发逻辑:
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {HttpServletRequest processedRequest = request;HandlerExecutionChain mappedHandler = null;ModelAndView mv = null;try {// 1. 文件上传请求处理processedRequest = checkMultipart(request);// 2. 确定处理器执行链(包含拦截器)mappedHandler = getHandler(processedRequest);if (mappedHandler == null) {noHandlerFound(processedRequest, response);return;}// 3. 确定处理器适配器HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());// 4. 拦截器预处理if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;}// 5. 实际执行处理器mv = ha.handle(processedRequest, response, mappedHandler.getHandler());// 6. 查找默认视图名(如果需要)applyDefaultViewName(processedRequest, mv);// 7. 拦截器后处理mappedHandler.applyPostHandle(processedRequest, response, mv);} catch (Exception ex) {// 异常处理dispatchException = ex;} catch (Throwable err) {dispatchException = new NestedServletException("Handler dispatch failed", err);}// 8. 处理结果(渲染视图或处理异常)processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
getHandler 方法详细实现:
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {if (this.handlerMappings != null) {// 遍历所有 HandlerMappingfor (HandlerMapping mapping : this.handlerMappings) {HandlerExecutionChain handler = mapping.getHandler(request);if (handler != null) {return handler;}}}return null;
}
🔍 处理器执行链构建
HandlerExecutionChain 结构分析:
public class HandlerExecutionChain {private final Object handler;private final List<HandlerInterceptor> interceptorList = new ArrayList<>();private int interceptorIndex = -1;/*** 执行拦截器预处理*/boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {for (int i = 0; i < this.interceptorList.size(); i++) {HandlerInterceptor interceptor = this.interceptorList.get(i);if (!interceptor.preHandle(request, response, this.handler)) {// 预处理失败,触发已完成拦截器的afterCompletiontriggerAfterCompletion(request, response, null);return false;}this.interceptorIndex = i;}return true;}/*** 执行拦截器后处理*/void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView modelAndView) throws Exception {for (int i = this.interceptorList.size() - 1; i >= 0; i--) {HandlerInterceptor interceptor = this.interceptorList.get(i);interceptor.postHandle(request, response, this.handler, modelAndView);}}
}
🤝 四、核心组件协作机制
🎯 HandlerMapping 映射机制
RequestMappingHandlerMapping 工作原理:
public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping {/*** 扫描 @Controller 和 @RequestMapping 注解*/@Overridepublic void afterPropertiesSet() {super.afterPropertiesSet();// 1. 扫描所有Controller类Map<String, Object> beans = getApplicationContext().getBeansWithAnnotation(Controller.class);beans.putAll(getApplicationContext().getBeansWithAnnotation(RequestMapping.class));// 2. 解析每个Controller的方法for (Object bean : beans.values()) {Class<?> beanType = bean.getClass();RequestMapping typeMapping = beanType.getAnnotation(RequestMapping.class);// 3. 解析类级别的@RequestMappingRequestMappingInfo typeInfo = createRequestMappingInfo(typeMapping);// 4. 解析方法级别的@RequestMappingMethod[] methods = beanType.getDeclaredMethods();for (Method method : methods) {RequestMapping methodMapping = method.getAnnotation(RequestMapping.class);if (methodMapping != null) {RequestMappingInfo methodInfo = createRequestMappingInfo(methodMapping);RequestMappingInfo combinedInfo = typeInfo.combine(methodInfo);// 5. 注册映射关系registerHandlerMethod(bean, method, combinedInfo);}}}}/*** 根据请求查找处理器*/@Overrideprotected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {// 1. 获取请求路径String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);// 2. 查找匹配的HandlerMethodHandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);// 3. 创建处理器执行链(包含拦截器)return createHandlerExecutionChain(handlerMethod, request);}
}
⚡ HandlerAdapter 适配执行
RequestMappingHandlerAdapter 执行流程:
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter {/*** 支持 @Controller 注解的处理器*/@Overridepublic boolean supports(Object handler) {return handler instanceof HandlerMethod;}/*** 执行处理器方法*/@Overrideprotected ModelAndView handleInternal(HttpServletRequest request,HttpServletResponse response,HandlerMethod handlerMethod) throws Exception {// 1. 参数解析和绑定ServletWebRequest webRequest = new ServletWebRequest(request, response);try {// 2. 执行方法调用Object returnValue = invokeHandlerMethod(handlerMethod, webRequest);// 3. 处理返回值ModelAndView mav = getModelAndView(handlerMethod, returnValue, webRequest);return mav;} finally {// 4. 清理资源webRequest.requestCompleted();}}/*** 实际方法调用*/protected Object invokeHandlerMethod(HandlerMethod handlerMethod,ServletWebRequest webRequest) throws Exception {// 1. 创建方法调用器ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);// 2. 设置参数解析器invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);// 3. 设置返回值处理器invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);// 4. 执行方法调用Object returnValue = invocableMethod.invokeForRequest(webRequest, null);return returnValue;}
}
🎨 ViewResolver 视图解析
InternalResourceViewResolver 实现:
public class InternalResourceViewResolver extends UrlBasedViewResolver {/*** 解析视图名称*/@Overrideprotected View createView(String viewName, Locale locale) throws Exception {// 1. 检查重定向视图if (viewName.startsWith(REDIRECT_URL_PREFIX)) {String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());return new RedirectView(redirectUrl, isRedirectContextRelative(), isRedirectHttp10Compatible());}// 2. 检查转发视图if (viewName.startsWith(FORWARD_URL_PREFIX)) {String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length());return new InternalResourceView(forwardUrl);}// 3. 创建普通视图return super.createView(viewName, locale);}/*** 构建完整视图路径*/@Overrideprotected String createViewName(String viewName, Locale locale) {return getPrefix() + viewName + getSuffix();}
}
📊 五、请求处理日志追踪
🔍 请求处理调试工具
请求追踪拦截器:
@Component
@Slf4j
public class RequestTracingInterceptor implements HandlerInterceptor {private static final ThreadLocal<Long> startTimeHolder = new ThreadLocal<>();private static final ThreadLocal<String> requestIdHolder = new ThreadLocal<>();@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 1. 记录请求开始时间long startTime = System.currentTimeMillis();startTimeHolder.set(startTime);// 2. 生成请求IDString requestId = UUID.randomUUID().toString().substring(0, 8);requestIdHolder.set(requestId);// 3. 记录请求信息log.info("🔍 [{}] 请求开始: {} {} [Handler: {}]", requestId, request.getMethod(), request.getRequestURI(),getHandlerDescription(handler));// 4. 记录请求参数logRequestParameters(request, requestId);return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {String requestId = requestIdHolder.get();log.info("✅ [{}] 控制器执行完成 [View: {}]", requestId, modelAndView != null ? modelAndView.getViewName() : "N/A");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {long endTime = System.currentTimeMillis();long startTime = startTimeHolder.get();long duration = endTime - startTime;String requestId = requestIdHolder.get();if (ex != null) {log.error("❌ [{}] 请求处理异常: {} [耗时: {}ms]", requestId, ex.getMessage(), duration);} else {log.info("🎯 [{}] 请求处理完成 [状态: {}] [耗时: {}ms]", requestId, response.getStatus(), duration);}// 清理ThreadLocalstartTimeHolder.remove();requestIdHolder.remove();}private String getHandlerDescription(Object handler) {if (handler instanceof HandlerMethod) {HandlerMethod handlerMethod = (HandlerMethod) handler;return String.format("%s.%s", handlerMethod.getBeanType().getSimpleName(),handlerMethod.getMethod().getName());}return handler.getClass().getSimpleName();}private void logRequestParameters(HttpServletRequest request, String requestId) {Map<String, String[]> parameterMap = request.getParameterMap();if (!parameterMap.isEmpty()) {StringBuilder params = new StringBuilder();for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {params.append(entry.getKey()).append("=").append(Arrays.toString(entry.getValue())).append("; ");}log.debug("📋 [{}] 请求参数: {}", requestId, params.toString());}}
}
📝 完整请求处理日志示例
典型请求处理日志输出:
2023-10-01 10:00:01.123 INFO 🔍 [a1b2c3d4] 请求开始: GET /api/users/123 [Handler: UserController.getUser]
2023-10-01 10:00:01.124 DEBUG 📋 [a1b2c3d4] 请求参数: id=123;
2023-10-01 10:00:01.125 DEBUG 🔄 [a1b2c3d4] HandlerMapping找到处理器: UserController.getUser
2023-10-01 10:00:01.126 DEBUG ⚡ [a1b2c3d4] HandlerAdapter执行方法调用
2023-10-01 10:00:01.127 DEBUG 🗃️ [a1b2c3d4] 查询数据库获取用户数据
2023-10-01 10:00:01.128 INFO ✅ [a1b2c3d4] 控制器执行完成 [View: user/details]
2023-10-01 10:00:01.129 DEBUG 🎨 [a1b2c3d4] ViewResolver解析视图: /WEB-INF/views/user/details.jsp
2023-10-01 10:00:01.130 INFO 🎯 [a1b2c3d4] 请求处理完成 [状态: 200] [耗时: 7ms]
🔧 调试配置启用
Spring MVC 调试配置:
# application.properties - 启用详细调试日志
logging.level.org.springframework.web=DEBUG
logging.level.com.example.controller=TRACE# 启用Spring MVC调试功能
spring.mvc.log-request-details=true
spring.mvc.log-resolved-exceptions=true# 启用参数绑定日志
logging.level.org.springframework.web.bind=TRACE
💡 六、性能优化与最佳实践
⚡ 组件配置优化
高性能 DispatcherServlet 配置:
@Configuration
@EnableWebMvc
public class WebMvcOptimizationConfig implements WebMvcConfigurer {/*** 优化HandlerMapping配置*/@Overridepublic void configurePathMatch(PathMatchConfigurer configurer) {// 1. 禁用后缀模式匹配(提高性能)configurer.setUseSuffixPatternMatch(false);// 2. 禁用尾随斜杠匹配configurer.setUseTrailingSlashMatch(false);// 3. 注册路径匹配器(缓存URL路径)AntPathMatcher pathMatcher = new AntPathMatcher();pathMatcher.setCachePatterns(true);configurer.setPathMatcher(pathMatcher);}/*** 配置异步处理*/@Overridepublic void configureAsyncSupport(AsyncSupportConfigurer configurer) {// 1. 设置异步请求超时时间configurer.setDefaultTimeout(30000);// 2. 注册异步拦截器configurer.registerCallableInterceptors(new TimeoutCallableProcessingInterceptor());configurer.registerDeferredResultInterceptors(new TimeoutDeferredResultProcessingInterceptor());}/*** 优化静态资源处理*/@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {// 1. 启用缓存控制registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/").setCacheControl(CacheControl.maxAge(30, TimeUnit.DAYS));}/*** 配置拦截器*/@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 1. 性能监控拦截器registry.addInterceptor(new RequestTracingInterceptor()).addPathPatterns("/api/**");// 2. 缓存控制拦截器registry.addInterceptor(new CacheControlInterceptor()).addPathPatterns("/static/**");}
}
🚀 异步处理优化
异步控制器实现
@RestController
@Slf4j
public class AsyncUserController {@Autowiredprivate UserService userService;/*** 异步处理用户查询*/@GetMapping("/async/users/{id}")public Callable<User> getUserAsync(@PathVariable Long id) {log.info("主线程接收请求: {}", Thread.currentThread().getName());return () -> {log.info("异步线程处理请求: {}", Thread.currentThread().getName());// 模拟耗时操作Thread.sleep(1000);return userService.getUserById(id);};}/*** DeferredResult 异步处理*/@GetMapping("/async/users/{id}/deferred")public DeferredResult<User> getUserDeferred(@PathVariable Long id) {DeferredResult<User> deferredResult = new DeferredResult<>(5000L); // 5秒超时// 异步处理任务CompletableFuture.supplyAsync(() -> userService.getUserById(id)).whenComplete((result, throwable) -> {if (throwable != null) {deferredResult.setErrorResult(throwable);} else {deferredResult.setResult(result);}});// 超时处理deferredResult.onTimeout(() -> {log.warn("用户查询超时: {}", id);deferredResult.setErrorResult(new TimeoutException("查询超时"));});return deferredResult;}
}
🔍 性能监控端点
MVC 性能监控配置:
@RestController
@Endpoint(id = "mvc-metrics")
public class MvcMetricsEndpoint {@Autowiredprivate RequestMappingHandlerMapping handlerMapping;@ReadOperationpublic Map<String, Object> getMvcMetrics() {Map<String, Object> metrics = new HashMap<>();// 1. 获取所有映射信息Map<RequestMappingInfo, HandlerMethod> handlerMethods = handlerMapping.getHandlerMethods();metrics.put("totalMappings", handlerMethods.size());metrics.put("mappingDetails", getMappingDetails(handlerMethods));// 2. 获取性能统计metrics.put("performance", getPerformanceStats());return metrics;}private List<Map<String, Object>> getMappingDetails(Map<RequestMappingInfo, HandlerMethod> handlerMethods) {List<Map<String, Object>> details = new ArrayList<>();for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : handlerMethods.entrySet()) {Map<String, Object> mappingInfo = new HashMap<>();mappingInfo.put("pattern", entry.getKey().getPatternsCondition());mappingInfo.put("method", entry.getKey().getMethodsCondition());mappingInfo.put("handler", entry.getValue().getMethod().getName());mappingInfo.put("controller", entry.getValue().getBeanType().getSimpleName());details.add(mappingInfo);}return details;}
}
📊 优化效果对比
优化前后性能对比:
| 优化项 | 优化前 | 优化后 | 提升幅度 | 主要优化措施 |
|---|---|---|---|---|
| 请求处理时间 | 15 ms | 8 ms | 🔼 46.7 % | 精确包扫描、异步化处理、线程池参数优化 |
| 内存占用 | 512 MB | 384 MB | 🔼 25 % | 启用懒加载、按需装配、Bean 作用域精简 |
| 并发处理能力(QPS) | 1000 | 1800 | 🔼 80 % | 优化连接池、Redis Pipeline、批量SQL执行 |
| 启动时间 | 12 s | 7 s | 🔼 41.7 % | 移除无关自动配置、懒加载、类加载并行化 |
