一、Spring MVC概述与启动流程
1.1 Spring MVC在Spring Boot中的角色
虽然Spring Boot简化了配置,但其底层仍然使用Spring MVC处理Web请求。传统方式通过web.xml配置DispatcherServlet,而在Spring Boot中则通过自动配置完成。
1.2 DispatcherServlet初始化流程
Tomcat启动时:
-
创建
DispatcherServlet对象 -
调用其
init()方法 -
在
init()中创建Spring容器,并添加ContextRefreshListener -
Spring容器刷新完成后触发
ContextRefreshedEvent -
执行
initStrategies()初始化九大组件
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context); // 核心
initHandlerAdapters(context); // 核心
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}
二、Handler与HandlerMapping详解
2.1 四种Handler类型
Spring MVC支持四种处理器:
-
实现
Controller接口的Bean@Component("/test") public class MyController implements Controller { @Override public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) { return new ModelAndView(); } } -
实现
HttpRequestHandler接口的Bean@Component("/test") public class MyHttpHandler implements HttpRequestHandler { @Override public void handleRequest(HttpServletRequest request, HttpServletResponse response) { // 直接操作request/response } } -
@RequestMapping注解的方法(最常用)@RestController public class MyController { @GetMapping("/test") public String test(String username) { return "Hello " + username; } } -
HandlerFunction对象(函数式Web)@Bean public RouterFunction<ServerResponse> router() { return route() .GET("/test", request -> ok().body("Hello")) .build(); }
2.2 三种HandlerMapping及其工作原理
1. BeanNameUrlHandlerMapping
-
负责处理
Controller和HttpRequestHandler接口的实现类 -
查找逻辑:
// 简化逻辑 for (String beanName : beanFactory.getBeanNamesForType(Object.class)) { if (beanName.startsWith("/")) { handlerMap.put(beanName, beanFactory.getBean(beanName)); } }
2. RequestMappingHandlerMapping
-
负责处理
@RequestMapping注解的方法 -
查找流程:
-
扫描所有Bean类型
-
判断是否有
@Controller或@RequestMapping注解 -
解析类和方法上的
@RequestMapping -
封装为
RequestMappingInfo->HandlerMethod映射 -
存入
registry(Map结构)
-
3. RouterFunctionMapping
-
负责处理
RouterFunction及其包含的HandlerFunction -
建立路径到
HandlerFunction的映射
2.3 Handler查找流程
// DispatcherServlet中的查找逻辑
protected HandlerExecutionChain getHandler(HttpServletRequest request) {
for (HandlerMapping mapping : this.handlerMappings) {
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler; // 找到即返回,遍历顺序决定优先级
}
}
return null;
}
优先级顺序(默认):
-
BeanNameUrlHandlerMapping -
RequestMappingHandlerMapping -
RouterFunctionMapping
这意味着如果同一个路径被多种Handler处理,先注册的生效。
三、HandlerAdapter与执行适配
3.1 为什么需要HandlerAdapter?
不同类型的Handler执行方式不同:
-
Controller:调用handleRequest() -
HttpRequestHandler:调用handleRequest() -
HandlerMethod:反射调用对应方法 -
HandlerFunction:调用handle()
HandlerAdapter采用适配器模式,统一调用接口。
3.2 四种HandlerAdapter
1. HttpRequestHandlerAdapter
public boolean supports(Object handler) {
return (handler instanceof HttpRequestHandler);
}
public ModelAndView handle(HttpServletRequest request,
HttpServletResponse response, Object handler) {
((HttpRequestHandler) handler).handleRequest(request, response);
return null;
}
2. SimpleControllerHandlerAdapter
public boolean supports(Object handler) {
return (handler instanceof Controller);
}
public ModelAndView handle(HttpServletRequest request,
HttpServletResponse response, Object handler) {
return ((Controller) handler).handleRequest(request, response);
}
3. RequestMappingHandlerAdapter
public final boolean supports(Object handler) {
return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}
这是最复杂的Adapter,负责执行@RequestMapping方法。
4. HandlerFunctionAdapter
public boolean supports(Object handler) {
return handler instanceof HandlerFunction;
}
3.3 适配器查找流程
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
for (HandlerAdapter adapter : this.handlerAdapters) {
if (adapter.supports(handler)) {
return adapter; // 找到支持该Handler的Adapter
}
}
throw new ServletException("No adapter for handler [" + handler + "]");
}
四、方法参数解析器(HandlerMethodArgumentResolver)
4.1 参数注解与数据来源
| 注解 | 数据来源 | 解析器 |
|---|---|---|
@RequestParam |
请求参数 | RequestParamMethodArgumentResolver |
@RequestHeader |
请求头 | RequestHeaderMethodArgumentResolver |
@SessionAttribute |
Session属性 | SessionAttributeMethodArgumentResolver |
@RequestAttribute |
Request属性 | RequestAttributeMethodArgumentResolver |
@RequestBody |
请求体 | RequestResponseBodyMethodProcessor |
| 无注解(简单类型) | 请求参数 | RequestParamMethodArgumentResolver |
4.2 参数解析流程
private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
if (result == null) {
// 遍历所有解析器
for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) {
if (resolver.supportsParameter(parameter)) {
result = resolver;
this.argumentResolverCache.put(parameter, result);
break;
}
}
}
return result;
}
注意 :解析器有顺序,先匹配的先使用。例如@RequestParam比@SessionAttribute优先级高。
4.3 RequestParam解析示例
// RequestParamMethodArgumentResolver的核心逻辑
protected Object resolveName(String name, MethodParameter parameter,
NativeWebRequest request) {
// 1. 尝试从Multipart请求获取
Object arg = resolveMultipartArgument(name, parameter, request);
// 2. 从普通请求参数获取
if (arg == null) {
String[] paramValues = request.getParameterValues(name);
if (paramValues != null) {
arg = (paramValues.length == 1 ? paramValues[0] : paramValues);
}
}
return arg;
}
五、方法返回值处理器(HandlerMethodReturnValueHandler)
5.1 返回值处理类型
| 返回值类型 | 处理器 | 说明 |
|---|---|---|
@ResponseBody |
RequestResponseBodyMethodProcessor |
将返回值写入响应体 |
String(无@ResponseBody) |
ViewNameMethodReturnValueHandler |
作为视图名进行视图解析 |
Model |
ModelMethodProcessor |
添加到Model中 |
ModelAndView |
ModelAndViewMethodReturnValueHandler |
直接返回ModelAndView |
5.2 @ResponseBody处理流程
RequestResponseBodyMethodProcessor使用HttpMessageConverter将返回值转换为HTTP响应。
5.3 常用HttpMessageConverter
-
ByteArrayHttpMessageConverter:字节数组
-
StringHttpMessageConverter:字符串(默认ISO-8859-1编码)
-
SourceHttpMessageConverter:XML源
-
MappingJackson2HttpMessageConverter:JSON转换(需添加Jackson依赖)
5.4 中文乱码解决方案
方案一:在@RequestMapping中指定
@RequestMapping(path = "/test", produces = "application/json;charset=UTF-8")
@ResponseBody
public String test() {
return "中文";
}
方案二:自定义StringHttpMessageConverter
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
StringHttpMessageConverter converter = new StringHttpMessageConverter();
converter.setDefaultCharset(StandardCharsets.UTF_8);
converters.add(0, converter); // 添加到最前面
}
}
方案三:添加JSON Converter
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
MappingJackson2HttpMessageConverter converter =
new MappingJackson2HttpMessageConverter();
converter.setDefaultCharset(StandardCharsets.UTF_8);
converters.add(converter);
}
}
六、完整请求处理流程
6.1 流程图概述
6.2 源码关键节点
-
DispatcherServlet.doDispatch():请求分发入口
-
AbstractHandlerMapping.getHandler():获取HandlerExecutionChain
-
RequestMappingHandlerAdapter.invokeHandlerMethod():执行@RequestMapping方法
-
HandlerMethodArgumentResolverComposite.resolveArgument():解析所有参数
-
RequestResponseBodyMethodProcessor.handleReturnValue():处理@ResponseBody返回值
七、总结与最佳实践
7.1 核心组件关系
-
HandlerMapping:路由映射,建立路径到Handler的映射
-
HandlerAdapter:执行适配,统一不同Handler的调用方式
-
HandlerMethodArgumentResolver:参数解析,从请求中提取数据
-
HandlerMethodReturnValueHandler:返回值处理,将结果转换为HTTP响应
7.2 性能优化建议
-
合理使用Handler类型 :优先使用
@RequestMapping,它最灵活且功能最全 -
减少反射调用:避免在Controller中使用过多的动态参数
-
合理配置MessageConverter:只添加需要的Converter,减少遍历开销
-
利用缓存:Spring MVC会缓存参数解析器、返回值处理器等
7.3 常见问题排查
-
404问题:检查HandlerMapping是否正常注册,路径映射是否正确
-
参数绑定失败:检查参数解析器是否支持该参数类型
-
中文乱码:检查StringHttpMessageConverter编码设置
-
返回值处理异常:检查是否缺少对应的HttpMessageConverter
7.4 扩展点
-
自定义HandlerMapping :实现
HandlerMapping接口 -
自定义HandlerAdapter :实现
HandlerAdapter接口 -
自定义参数解析器 :实现
HandlerMethodArgumentResolver -
自定义返回值处理器 :实现
HandlerMethodReturnValueHandler