springmvc的核心组件有哪些

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


Spring MVC 核心组件一览

组件 类型 职责 是否可扩展
DispatcherServlet Servlet(前端控制器) 统一接收请求,调度整个处理流程 可继承扩展
HandlerMapping 接口 请求 → 处理器的映射 多个实现
HandlerAdapter 接口 适配不同处理器类型执行调用 多个实现
Handler Controller/方法 实际处理业务逻辑 用户编写
ModelAndView 对象 封装模型数据和视图信息 -
ViewResolver 接口 视图名 → 具体 View 对象 多个实现
View 接口 渲染最终输出(HTML/JSON等) 多个实现
HandlerExceptionResolver 接口 统一异常处理 可自定义
HandlerInterceptor 接口 处理器拦截(前置/后置/完成) 可自定义

请求处理完整流程

scss 复制代码
┌─────────────────────────────────────────────────────────────────┐
│                         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(核心入口)

java 复制代码
// 继承 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(请求映射)

java 复制代码
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(适配执行)

java 复制代码
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. 参数解析与返回值处理

java 复制代码
// 参数解析器(内置 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

java 复制代码
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. 异常处理

java 复制代码
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 配置:

java 复制代码
// 自动配置类: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
相关推荐
IT_陈寒10 分钟前
SpringBoot自动配置没生效?你可能漏了这个注解
前端·人工智能·后端
长明14 分钟前
C#项目组织与概念梳理
后端·c#
xn713320 分钟前
个人网站站外分发怎么做归因?我给 XBSTACK 补了一套 UTM 追踪规则
后端·低代码
用户23307130747922 分钟前
JUC 并发容器与工具
后端
冰暮流星35 分钟前
flask之模版渲染
后端·python·flask
威武的花瓣43 分钟前
细说ASP.NET的各种异步操作
后端·asp.net·php
漂亮的摩托1 小时前
如何编写一个SpringBoot项目告警推送的Starter
java·spring boot·后端
任性的芝麻1 小时前
ASP.NET MVC 中的异步方式
后端·asp.net·mvc
雨师@1 小时前
go语言项目--实例化(图书管理)--006
开发语言·后端·golang
kuro-shiro1 小时前
SpringBoot 启动流程
java·spring boot·后端