springmvc的核心组件有哪些

1 阅读5分钟

好的,Spring MVC 核心组件是面试高频考点,需要清晰理解每个组件的职责和协作流程。


Spring MVC 核心组件一览

组件类型职责是否可扩展
DispatcherServletServlet(前端控制器)统一接收请求,调度整个处理流程可继承扩展
HandlerMapping接口请求 → 处理器的映射多个实现
HandlerAdapter接口适配不同处理器类型执行调用多个实现
HandlerController/方法实际处理业务逻辑用户编写
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