好的,Spring MVC 核心组件是面试高频考点,需要清晰理解每个组件的职责和协作流程。
Spring MVC 核心组件一览
| 组件 | 类型 | 职责 | 是否可扩展 |
|---|---|---|---|
| DispatcherServlet | Servlet(前端控制器) | 统一接收请求,调度整个处理流程 | 可继承扩展 |
| HandlerMapping | 接口 | 请求 → 处理器的映射 | 多个实现 |
| HandlerAdapter | 接口 | 适配不同处理器类型执行调用 | 多个实现 |
| Handler | Controller/方法 | 实际处理业务逻辑 | 用户编写 |
| ModelAndView | 对象 | 封装模型数据和视图信息 | - |
| ViewResolver | 接口 | 视图名 → 具体 View 对象 | 多个实现 |
| View | 接口 | 渲染最终输出(HTML/JSON等) | 多个实现 |
| HandlerExceptionResolver | 接口 | 统一异常处理 | 可自定义 |
| HandlerInterceptor | 接口 | 处理器拦截(前置/后置/完成) | 可自定义 |
请求处理完整流程
┌─────────────────────────────────────────────────────────────────┐
│ HTTP Request │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 1. DispatcherServlet (doDispatch) │
│ ├── 调用 doService() 设置请求属性 │
│ └── 进入 doDispatch() 核心分发 │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 2. HandlerMapping 链(遍历查找) │
│ ├── RequestMappingHandlerMapping(@RequestMapping) │
│ ├── BeanNameUrlHandlerMapping(Bean 名称映射) │
│ └── RouterFunctionMapping(函数式路由) │
│ │
│ 返回:HandlerExecutionChain(处理器 + Interceptor 链) │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 3. HandlerInterceptor.preHandle() │
│ ├── 权限校验、日志记录、跨域处理等 │
│ └── 返回 false 则中断流程 │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 4. HandlerAdapter 适配执行 │
│ ├── RequestMappingHandlerAdapter(@Controller 方法) │
│ ├── HttpRequestHandlerAdapter(HttpRequestHandler) │
│ └── SimpleControllerHandlerAdapter(Controller 接口) │
│ │
│ 内部调用:参数解析(HandlerMethodArgumentResolver) │
│ 返回值处理(HandlerMethodReturnValueHandler) │
│ 数据绑定(WebDataBinder) │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 5. Handler 执行业务逻辑 │
│ └── 返回 ModelAndView(或 @ResponseBody 直接输出) │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 6. HandlerInterceptor.postHandle() │
│ └── 后置处理(可修改 ModelAndView) │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 7. 处理异常(如有) │
│ └── HandlerExceptionResolver(@ExceptionHandler 等) │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 8. ViewResolver 解析视图 │
│ ├── InternalResourceViewResolver(JSP) │
│ ├── ThymeleafViewResolver │
│ └── ContentNegotiatingViewResolver(协商决定) │
│ │
│ 返回:具体 View 对象 │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 9. View.render() 渲染输出 │
│ └── 生成 HTML / 其他响应内容 │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 10. HandlerInterceptor.afterCompletion() │
│ └── 资源清理、日志记录等 │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ HTTP Response │
└─────────────────────────────────────────────────────────────────┘
各组件详解
1. DispatcherServlet(核心入口)
// 继承 FrameworkServlet → HttpServletBean → HttpServlet
public class DispatcherServlet extends FrameworkServlet {
// 核心组件集合
private List<HandlerMapping> handlerMappings;
private List<HandlerAdapter> handlerAdapters;
private List<HandlerExceptionResolver> handlerExceptionResolvers;
private List<ViewResolver> viewResolvers;
// 核心分发方法
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
try {
ModelAndView mv = null;
Exception dispatchException = null;
// 1. 检查 Multipart(文件上传)
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// 2. 获取处理器链(Handler + Interceptors)
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. 后置拦截
mappedHandler.applyPostHandle(processedRequest, response, mv);
// 7. 处理结果(渲染视图或异常)
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
} catch (Exception ex) {
// ...
} finally {
// 8. 完成回调
if (mappedHandler != null) {
mappedHandler.triggerAfterCompletion(processedRequest, response, null);
}
cleanupMultipart(processedRequest);
}
}
}
2. HandlerMapping(请求映射)
public interface HandlerMapping {
// 查找处理器,返回 HandlerExecutionChain
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}
// 主要实现类
public abstract class AbstractHandlerMapping implements HandlerMapping {
private final List<Object> interceptors = new ArrayList<>();
public final HandlerExecutionChain getHandler(HttpServletRequest request) {
Object handler = getHandlerInternal(request); // 子类实现查找逻辑
if (handler == null) return null;
// 包装为 Chain,加入拦截器
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
return executionChain;
}
}
// 最常用的实现:处理 @RequestMapping
public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping {
@Override
protected void initHandlerMethods() {
// 扫描所有 @Controller 类中的 @RequestMapping 方法
for (String beanName : getCandidateBeanNames()) {
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
processCandidateBean(beanName);
}
}
}
// 建立映射关系:RequestMappingInfo → HandlerMethod
protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) {
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
this.mappingRegistry.register(mapping, handlerMethod);
}
}
3. HandlerAdapter(适配执行)
public interface HandlerAdapter {
boolean supports(Object handler); // 是否支持该处理器
ModelAndView handle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception;
}
// 注解方法适配器(最常用)
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter {
private List<HandlerMethodArgumentResolver> customArgumentResolvers;
private List<HandlerMethodReturnValueHandler> customReturnValueHandlers;
@Override
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
// 1. 准备 ModelAndViewContainer
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
modelFactory.initModel(webRequest, mavContainer, invocableMethod);
// 2. 调用处理器方法(核心)
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
invocableMethod.invokeAndHandle(webRequest, mavContainer);
// 3. 返回 ModelAndView(或 null 如果已直接响应)
return getModelAndView(mavContainer, modelFactory, webRequest);
}
}
4. 参数解析与返回值处理
// 参数解析器(内置 20+ 个)
public interface HandlerMethodArgumentResolver {
boolean supportsParameter(MethodParameter parameter);
Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory);
}
// 常用解析器
@RequestBody → RequestResponseBodyMethodProcessor(JSON 反序列化)
@RequestParam → RequestParamMethodArgumentResolver
@PathVariable → PathVariableMethodArgumentResolver
@ModelAttribute → ServletModelAttributeMethodProcessor
HttpServletRequest → ServletRequestMethodArgumentResolver
Principal → PrincipalMethodArgumentResolver
// 返回值处理器
public interface HandlerMethodReturnValueHandler {
boolean supportsReturnType(MethodParameter returnType);
void handleReturnValue(Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest);
}
@ResponseBody → RequestResponseBodyMethodProcessor(JSON 序列化)
String(视图名) → ViewNameMethodReturnValueHandler
ModelAndView → ModelAndViewMethodReturnValueHandler
void → VoidMethodReturnValueHandler
5. ViewResolver & View
public interface ViewResolver {
View resolveViewName(String viewName, Locale locale) throws Exception;
}
public interface View {
void render(Map<String, ?> model, HttpServletRequest request,
HttpServletResponse response) throws Exception;
}
// 内部资源解析(JSP)
public class InternalResourceViewResolver extends UrlBasedViewResolver {
@Override
protected View loadView(String viewName, Locale locale) throws Exception {
// 前缀 + viewName + 后缀 = /WEB-INF/views/home.jsp
String url = getPrefix() + viewName + getSuffix();
return new InternalResourceView(url);
}
}
// 内容协商解析(根据 Accept 头决定)
public class ContentNegotiatingViewResolver implements ViewResolver {
@Override
public View resolveViewName(String viewName, Locale locale) throws Exception {
// 1. 获取请求的 MediaType(application/json, text/html 等)
List<MediaType> requestedMediaTypes = getMediaTypes(request);
// 2. 遍历所有 ViewResolver 获取候选 View
for (ViewResolver viewResolver : this.viewResolvers) {
View view = viewResolver.resolveViewName(viewName, locale);
if (view != null) candidates.add(view);
}
// 3. 选择最佳匹配 MediaType 的 View
return getBestView(candidates, requestedMediaTypes);
}
}
6. 异常处理
public interface HandlerExceptionResolver {
ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex);
}
// Spring Boot 默认组合解析器
public class HandlerExceptionResolverComposite implements HandlerExceptionResolver {
private List<HandlerExceptionResolver> resolvers;
@Override
public ModelAndView resolveException(...) {
for (HandlerExceptionResolver resolver : this.resolvers) {
ModelAndView mav = resolver.resolveException(request, response, handler, ex);
if (mav != null) return mav;
}
return null;
}
}
// 具体实现
ExceptionHandlerExceptionResolver // 处理 @ExceptionHandler
ResponseStatusExceptionResolver // 处理 @ResponseStatus
DefaultHandlerExceptionResolver // 处理标准 Spring 异常
现代 Spring Boot 的简化
Spring Boot 自动配置替换了大量 XML 配置:
// 自动配置类:DispatcherServletAutoConfiguration
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass(DispatcherServlet.class)
@AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class)
public class DispatcherServletAutoConfiguration {
@Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
public DispatcherServlet dispatcherServlet(HttpProperties httpProperties,
WebMvcProperties webMvcProperties) {
DispatcherServlet dispatcherServlet = new DispatcherServlet();
dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest());
dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest());
dispatcherServlet.setThrowExceptionIfNoHandlerFound(webMvcProperties.isThrowExceptionIfNoHandlerFound());
return dispatcherServlet;
}
@Bean
@ConditionalOnBean(MultipartResolver.class)
@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)
public MultipartResolver multipartResolver(MultipartResolver resolver) {
// 防止命名冲突,包装为 StandardServletMultipartResolver
return resolver;
}
}
// WebMvcAutoConfiguration 配置其他组件
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class) // 用户未自定义时生效
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class })
public class WebMvcAutoConfiguration {
// 配置 HandlerMapping、HandlerAdapter、ViewResolver 等
}
面试要点总结
| 问题 | 核心回答 |
|---|---|
| 为什么需要 HandlerAdapter | 处理器类型多样(Controller 接口、@Controller 注解、HttpRequestHandler),适配器模式统一调用方式 |
| HandlerMapping 执行链 | 多个 Mapping 按顺序匹配,第一个返回非 null 即停止 |
| @Controller 如何被识别 | RequestMappingHandlerMapping 扫描 @Controller 类中的 @RequestMapping 方法,建立 URL → Method 映射 |
| 拦截器 vs 过滤器 | Filter 是 Servlet 规范,在 DispatcherServlet 之前;Interceptor 是 Spring 的,在 Handler 前后,能访问 ModelAndView |
| 如何自定义参数解析 | 实现 HandlerMethodArgumentResolver,注册到 RequestMappingHandlerAdapter |