一、前后端分离架构下的SpringMVC流程重塑
1.1 核心组件交互流程(重点!)
sequenceDiagram
participant Client
participant DispatcherServlet
participant HandlerMapping
participant HandlerAdapter
participant Controller
participant MessageConverter
Client->>DispatcherServlet: HTTP Request
DispatcherServlet->>HandlerMapping: 获取HandlerExecutionChain
HandlerMapping-->>DispatcherServlet: 返回Chain(包含拦截器链)
DispatcherServlet->>Interceptor: preHandle()顺序执行
Interceptor-->>DispatcherServlet: 是否放行
alt 全部通过
DispatcherServlet->>HandlerAdapter: 获取适配器
HandlerAdapter->>MessageConverter: 反序列化请求体
HandlerAdapter->>Controller: 执行方法
Controller-->>HandlerAdapter: 返回结果对象
HandlerAdapter->>MessageConverter: 序列化响应体
HandlerAdapter-->>DispatcherServlet: ModelAndView
DispatcherServlet->>Interceptor: postHandle()逆序执行
else 拦截
DispatcherServlet->>Client: 直接返回错误
end
DispatcherServlet->>Interceptor: afterCompletion()逆序执行
DispatcherServlet-->>Client: HTTP Response
二、核心源码解析
2.1 DispatcherServlet入口方法
protected void doDispatch(HttpServletRequest req, HttpServletResponse resp) {
HandlerExecutionChain mappedHandler = getHandler(processedRequest);
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
if (!mappedHandler.applyPreHandle(processedRequest, response)) return;
ModelAndView mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
mappedHandler.applyPostHandle(processedRequest, response, mv);
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
2.2 RequestMappingHandlerMapping
public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping {
protected void detectHandlerMethods(Object handler) {
Class<?> handlerType = (handler instanceof String ?
getApplicationContext().getType((String) handler) : handler.getClass());
Map<Method, RequestMappingInfo> methods = MethodIntrospector.selectMethods(handlerType,
(MethodIntrospector.MetadataLookup<RequestMappingInfo>) method -> getMappingForMethod(method, handlerType));
methods.forEach((method, mapping) -> registerHandlerMethod(handler, method, mapping));
}
}
2.3 RequestMappingHandlerAdapter
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter {
protected ModelAndView handleInternal(HttpServletRequest req, HttpServletResponse res, HandlerMethod handlerMethod) {
Object[] args = getMethodArgumentValues(request, response, handlerMethod);
Object returnValue = invokeForRequest(req, res, handlerMethod, args);
return getModelAndView(returnValue, handlerMethod, req, res);
}
}
三、关键流程拆解
3.1 请求匹配阶段
graph TD
A[DispatcherServlet] --> B[遍历所有HandlerMapping]
B --> C{是否找到Handler?}
C -->|是| D[返回HandlerExecutionChain]
C -->|否| E[返回404错误]
3.2 参数处理流程
public interface HandlerMethodArgumentResolver {
boolean supportsParameter(MethodParameter parameter);
Object resolveArgument(...) throws Exception;
}
public class RequestResponseBodyMethodProcessor implements HandlerMethodArgumentResolver {
public Object resolveArgument(...) {
return readWithMessageConverters(webRequest, parameter, parameter.getNestedGenericParameterType());
}
}
四、SSM环境手动配置SpringMVC
4.1 web.xml配置
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
4.2 spring-mvc.xml核心配置
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
</mvc:message-converters>
</mvc:annotation-driven>
<context:component-scan base-package="com.example.controller"/>
<mvc:resources mapping="/static/**" location="/static/"/>
<mvc:interceptors>
<bean class="com.example.interceptor.LogInterceptor"/>
</mvc:interceptors>
五、Spring Boot自动配置对比
5.1 配置差异对比表
| 配置项 | SSM手动配置 | Spring Boot自动配置 |
|---|
| DispatcherServlet | web.xml声明 | 自动注册,默认路径/ |
| 消息转换器 | XML显式定义 | 根据依赖自动配置(如Jackson) |
| 组件扫描 | XML配置base-package | @SpringBootApplication隐含扫描 |
| 静态资源 | <mvc:resources> | 自动映射/static/** |
5.2 启动类模拟实现
public class SSMApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{RootConfig.class};
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebMvcConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
六、高频面试题深度解析
6.1 为什么需要HandlerAdapter?
- 解耦设计:DispatcherServlet无需知道具体Handler类型
- 扩展性:支持多种处理器(Controller、HttpRequestHandler等)
- 统一接口:提供统一的handle()方法入口
6.2 如何实现RESTful响应?
public class MappingJackson2HttpMessageConverter extends AbstractHttpMessageConverter<Object> {
protected void writeInternal(Object object, HttpOutputMessage outputMessage) {
objectMapper.writeValue(outputMessage.getBody(), object);
}
}
七、调试技巧与学习建议
7.1 关键断点设置
DispatcherServlet.doDispatch()
RequestMappingHandlerMapping.getHandler()
RequestMappingHandlerAdapter.handleInternal()
7.2 学习路线建议
- 从XML配置入手理解组件关系
- 通过DEBUG跟踪完整请求流程
- 对比Spring Boot自动配置源码(WebMvcAutoConfiguration)