SpringMVC请求处理流程源码解析(第1篇):请求入口与处理器映射

SpringMVC请求处理流程源码解析(第1篇):请求入口与处理器映射

SpringMVC是Spring Framework提供的Web层MVC框架,其核心设计思想是"前端控制器模式"。本文深入剖析从请求入收到响应返回的完整源码流程,揭示SpringMVC如何协调各组件完成请求处理。

目录

  1. 核心组件架构
  2. DispatcherServlet完整解析
  3. 请求处理完整流程时序
  4. HandlerMapping处理器映射
  5. SpringMVC初始化流程

1. 核心组件架构

1.1 SpringMVC组件全景图

辅助组件
HandlerExceptionResolver
ViewResolver
HandlerAdapter
HandlerMapping
前端控制器
HandlerInterceptor
preHandle
postHandle
afterCompletion
DispatcherServlet
RequestMappingHandlerMapping
BeanNameUrlHandlerMapping
SimpleUrlHandlerMapping
RequestMappingHandlerAdapter
HttpRequestHandlerAdapter
SimpleControllerHandlerAdapter
InternalResourceViewResolver
ThymeleafViewResolver
FreeMarkerViewResolver
ExceptionHandlerExceptionResolver
DefaultHandlerExceptionResolver
SimpleMappingExceptionResolver
LocaleResolver
ThemeResolver
FlashMapManager

1.2 核心接口类图

DispatcherServlet
+doDispatch(request, response)
+render(mv, request, response)
<<interface>>
HandlerMapping
+getHandler(request)
<<interface>>
HandlerAdapter
+supports(handler)
+handle(request, response, handler)
<<interface>>
HandlerInterceptor
+preHandle(request, response, handler)
+postHandle(request, response, handler, mv)
+afterCompletion(request, response, handler, ex)
HandlerExecutionChain
+applyPreHandle(request, response)
+applyPostHandle(request, response, mv)
+triggerAfterCompletion(request, response, ex)
<<interface>>
ViewResolver
+resolveViewName(name, locale)
<<interface>>
View
+render(model, request, response)
<<interface>>
HandlerExceptionResolver
+resolveException(request, response, handler, ex)

1.3 请求处理流程概览







HTTP Request
DispatcherServlet
getHandler

HandlerMapping查找
HandlerExecutionChain

Handler + Interceptors
Handler存在?
404 Not Found
getHandlerAdapter
HandlerAdapter选择
applyPreHandle

拦截器前置处理
全部通过?
afterCompletion清理
ha.handle执行处理器
applyPostHandle

拦截器后置处理
processDispatchResult

处理结果
有异常?
异常处理链
视图渲染
triggerAfterCompletion
HTTP Response


2. DispatcherServlet完整解析

2.1 继承体系

HttpServlet
GenericServlet
HttpServletBean
FrameworkServlet
-WebApplicationContext webApplicationContext
+processRequest(req, resp)
#doService(req, resp)
DispatcherServlet
-HandlerMapping[] handlerMappings
-HandlerAdapter[] handlerAdapters
+doDispatch(req, resp)

2.2 请求入口时序

FrameworkServlet DispatcherServlet Servlet容器 FrameworkServlet DispatcherServlet Servlet容器 设置LocaleContext 设置Attributes 调用doService service(request, response) processRequest(req, resp) doService(request, response) doDispatch(request, response)

2.3 Servlet容器请求入口

Servlet容器的入口是HttpServlet.service()方法,它根据HTTP方法分发到doGetdoPost等方法:

java 复制代码
// javax.servlet.http.HttpServlet
public abstract class HttpServlet extends GenericServlet {
    
    // Servlet 5.0+ 实现
    @Override
    public void service(ServletRequest req, ServletResponse res) {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        
        // 根据HTTP方法分发
        service(request, response);
    }
    
    protected void service(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        String method = req.getMethod();
        
        if (method.equals(METHOD_GET)) {
            doGet(req, resp);
        } else if (method.equals(METHOD_POST)) {
            doPost(req, resp);
        }
        // ... 其他HTTP方法
    }
}

2.4 FrameworkServlet.processRequest()核心逻辑

FrameworkServlet重写了service()方法,在处理请求前设置WebApplicationContext和LocaleContext:

java 复制代码
// org.springframework.web.servlet.FrameworkServlet
public abstract class FrameworkServlet extends HttpServletBean {
    
    private static final String THREAD_CONTEXT_ATTRIBUTES_ATTRIBUTE_KEY =
            FrameworkServlet.class.getName() + ".CONTEXT";
    
    @Override
    protected final void processRequest(HttpServletRequest request,
                                        HttpServletResponse response) {
        // 1. 记录开始时间,用于性能监控
        long startTime = System.currentTimeMillis();
        Throwable failureCause = null;
        
        // 2. 获取或初始化LocaleContext
        LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
        LocaleContext localeContext = buildLocaleContext(request);
        
        // 3. 获取或初始化RequestAttributes
        RequestAttributes previousAttributes = 
            RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes requestAttributes = 
            buildRequestAttributes(request, response, previousAttributes);
        
        // 4. 处理异步请求
        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
        asyncManager.registerCallableInterceptor(..., ...);
        
        // 5. 将LocaleContext和RequestAttributes绑定到ThreadLocal
        LocaleContextHolder.setLocaleContext(localeContext, 
            ThreadContextHolder.getinheritability());
        RequestContextHolder.setRequestAttributes(requestAttributes, 
            ThreadContextHolder.getinheritability());
        
        try {
            // 6. 执行实际的处理逻辑(子类实现)
            doService(request, response);
        } catch (ServletException | IOException | RuntimeException ex) {
            failureCause = ex;
            throw ex;
        } finally {
            // 7. 清理ThreadLocal,恢复之前的上下文
            LocaleContextHolder.setLocaleContext(previousLocaleContext, 
                inheritFromExecutor);
            RequestContextHolder.setRequestAttributes(previousAttributes, 
                inheritFromExecutor);
            
            // 8. 发布请求完成事件
            publishRequestHandledEvent(request, response, startTime, failureCause);
        }
    }
    
    protected abstract void doService(HttpServletRequest request, 
                                      HttpServletResponse response) throws Exception;
}

关键设计点

  1. ThreadLocal模式 :通过LocaleContextHolderRequestContextHolder将请求上下文绑定到当前线程
  2. 作用域传播 :通过RequestContextFilter可以将子线程的请求属性传播到父线程
  3. 事件发布publishRequestHandledEvent()发布RequestHandledEvent事件

2.5 DispatcherServlet.doService()核心逻辑

java 复制代码
// org.springframework.web.servlet.DispatcherServlet
public class DispatcherServlet extends FrameworkServlet {
    
    private FlashMapManager flashMapManager;
    private ThemeResolver themeResolver;
    private MultipartResolver multipartResolver;
    private LocaleResolver localeResolver;
    private List<ViewResolver> viewResolvers;
    private List<HandlerExceptionResolver> handlerExceptionResolvers;
    
    @Override
    protected void doService(HttpServletRequest request, 
                            HttpServletResponse response) {
        // 1. 记录请求日志(开发模式下)
        if (logger.isDebugEnabled()) {
            String resumed = 
                WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() 
                    ? " resumed" : "";
            logger.debug("DispatcherServlet with name '" + getServletName() + 
                "'" + resumed + " processing " + request.getMethod() + 
                " request for [" + getRequestUri(request) + "]");
        }
        
        // 2. 保存原始请求属性,用于include后恢复
        Map<String, Object> attributesSnapshot = null;
        if (DispatcherType.INCLUDE.equals(request.getDispatcherType())) {
            attributesSnapshot = new HashMap<>();
            Enumeration<String> attrNames = request.getAttributeNames();
            while (attrNames.hasMoreElements()) {
                String name = attrNames.nextElement();
                if (this.cleanupAfterInclude || 
                    name.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
                    attributesSnapshot.put(name, request.getAttribute(name));
                }
            }
        }
        
        // 3. 设置Web应用上下文到请求属性
        request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, 
            getWebApplicationContext());
        
        // 4. 设置LocaleResolver、ThemeResolver等辅助组件
        request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
        request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
        request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
        
        // 5. 处理FlashMap
        FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request);
        if (inputFlashMap != null) {
            request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, inputFlashMap);
        }
        
        // 6. 调用核心处理方法
        try {
            doDispatch(request, response);
        } finally {
            if (attributesSnapshot != null) {
                restoreAttributesAfterInclude(request, attributesSnapshot);
            }
        }
    }
}

2.6 doDispatch核心源码

java 复制代码
protected void doDispatch(HttpServletRequest request,
                         HttpServletResponse response) {
    HttpServletRequest processedRequest = request;
    HandlerExecutionChain mappedHandler = null;
    boolean multipartRequestParsed = false;

    try {
        ModelAndView mv = null;
        Exception dispatchException = null;

        try {
            // ==========================================
            // 步骤1: 文件上传处理
            // ==========================================
            processedRequest = checkMultipart(request);
            multipartRequestParsed = (processedRequest != request);

            // ==========================================
            // 步骤2: 获取处理器执行链
            // ==========================================
            mappedHandler = getHandler(processedRequest);
            if (mappedHandler == null) {
                noHandlerFound(processedRequest, response);
                return;
            }

            // ==========================================
            // 步骤3: 获取HandlerAdapter
            // ==========================================
            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);

        } catch (Exception ex) {
            dispatchException = ex;
        }

        // ==========================================
        // 步骤7: 处理结果
        // ==========================================
        processDispatchResult(processedRequest, response,
            mappedHandler, mv, dispatchException);

    } finally {
        if (multipartRequestParsed) {
            cleanupMultipart(processedRequest);
        }
    }
}

2.7 noHandlerFound源码解析

当找不到Handler时,SpringMVC的处理逻辑:

java 复制代码
protected void noHandlerFound(HttpServletRequest request, 
                              HttpServletResponse response) {
    for (HandlerExceptionResolver resolver : this.handlerExceptionResolvers) {
        Exception ex = new NoHandlerFoundException(request.getMethod(),
            getRequestUri(request), new NestedServletException("No handler"));
        
        ModelAndView mav = resolver.resolveException(request, response, null, ex);
        
        if (mav != null) {
            render(mav, request, response);
            return;
        }
    }
    
    response.sendError(HttpServletResponse.SC_NOT_FOUND);
}

2.8 render视图渲染源码

java 复制代码
protected void render(ModelAndView mv, HttpServletRequest request,
                    HttpServletResponse response) {
    // 1. 设置Locale
    Locale locale = (mv.getLocale() != null ? 
        mv.getLocale() : this.localeResolver.resolveLocale(request));
    response.setLocale(locale);
    
    // 2. 获取视图名
    String viewName = mv.getViewName();
    View view = null;
    
    // 3. 如果ModelAndView已包含View实例
    if (mv.getView() != null) {
        view = mv.getView();
    }
    
    // 4. 否则,通过ViewResolver解析视图名
    if (view == null) {
        for (ViewResolver resolver : this.viewResolvers) {
            view = resolver.resolveViewName(viewName, locale);
            if (view != null) {
                break;
            }
        }
    }
    
    // 5. 如果仍然没有找到视图
    if (view == null) {
        throw new ServletException(
            "Could not resolve view with name '" + mv.getViewName() + "'");
    }
    
    // 6. 执行视图渲染
    view.render(mv.getModel(), request, response);
}

2.9 doDispatch时序图

ViewResolver HandlerExceptionResolver Controller HandlerExecutionChain HandlerAdapter HandlerMapping DispatcherServlet ViewResolver HandlerExceptionResolver Controller HandlerExecutionChain HandlerAdapter HandlerMapping DispatcherServlet getHandler(request) HandlerExecutionChain getHandlerAdapter(handler) HandlerAdapter applyPreHandle() boolean handle() 调用Controller ModelAndView ModelAndView applyPostHandle() processDispatchResult() 异常处理 视图解析 + render() triggerAfterCompletion()


3. 请求处理完整流程时序

3.1 完整时序图

View ViewResolver ExceptionHandler Controller Interceptor2 Interceptor1 HandlerAdapter HandlerMapping DispatcherServlet HTTP Client View ViewResolver ExceptionHandler Controller Interceptor2 Interceptor1 HandlerAdapter HandlerMapping DispatcherServlet HTTP Client 1. HandlerMapping查找 2. 前置拦截 3. 处理器执行 4. 后置拦截 alt [有异常] HTTP Request getHandler(request) HandlerExecutionChain preHandle() true preHandle() true handle() invoke() ModelAndView ModelAndView postHandle() postHandle() resolveException() ModelAndView (error视图) resolveViewName() View render() afterCompletion() afterCompletion() HTTP Response

3.2 关键节点详解

  1. ha.handle
    解析参数
    调用Controller
    处理返回值
    返回ModelAndView
  2. applyPreHandle

    正序遍历
    调用preHandle
    返回true?
    triggerAfterCompletion
  3. getHandlerAdapter


    遍历handlerAdapters
    adapter.supports方法
    支持?
    返回HandlerAdapter
    下一个
  4. getHandler


    遍历handlerMappings
    匹配URL
    匹配?
    返回HandlerExecutionChain
    下一个
    404

4. HandlerMapping处理器映射

4.1 HandlerMapping体系

<<interface>>
HandlerMapping
+getHandler(request)
<<abstract>>
AbstractHandlerMapping
+getHandler(request)
#getHandlerInternal(request)
<<class>>
RequestMappingInfo
-PatternsRequestCondition patterns
-MethodsRequestCondition methods
-ProducesRequestCondition produces
RequestMappingHandlerMapping
-Map<RequestMappingInfo, HandlerMethod> handlerMethods
+getHandler(request)
<<abstract>>
AbstractUrlHandlerMapping
+registerHandler(urlPath, handler)
BeanNameUrlHandlerMapping
SimpleUrlHandlerMapping

4.2 HandlerMapping接口定义

java 复制代码
// org.springframework.web.servlet.HandlerMapping
public interface HandlerMapping {
    
    /**
     * 根据请求获取HandlerExecutionChain
     * @param request HTTP请求
     * @return HandlerExecutionChain包含处理器和拦截器链
     */
    HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
    
    // 请求属性key
    String BEST_MATCHING_HANDLER_ATTRIBUTE = 
        HandlerMapping.class.getName() + ".bestMatchingHandler";
    String BEST_MATCHING_PATTERN_ATTRIBUTE = 
        HandlerMapping.class.getName() + ".bestMatchingPattern";
    String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = 
        HandlerMapping.class.getName() + ".pathWithinHandlerMapping";
    String URI_TEMPLATE_VARIABLES_ATTRIBUTE = 
        HandlerMapping.class.getName() + ".uriTemplateVariables";
}

4.3 AbstractHandlerMapping源码

java 复制代码
// org.springframework.web.servlet.handler.AbstractHandlerMapping
public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
        implements HandlerMapping, Ordered {
    
    private final List<HandlerInterceptor> interceptors = new ArrayList<>();
    private HandlerInterceptor[] defaultInterceptors;
    
    @Override
    public final HandlerExecutionChain getHandler(HttpServletRequest request) {
        // 1. 子类实现:获取具体的Handler
        Object handler = getHandlerInternal(request);
        
        if (handler == null) {
            return null;
        }
        
        // 2. 如果返回的是String(Bean名称),查找Bean实例
        if (handler instanceof String) {
            String handlerName = (String) handler;
            handler = getApplicationContext().getBean(handlerName);
        }
        
        // 3. 构建HandlerExecutionChain
        HandlerExecutionChain chain = getHandlerExecutionChain(handler, request);
        
        // 4. 处理跨域配置
        if (CorsConfigurationSource.class.isAssignableFrom(handler.getClass())) {
            CorsConfiguration config = initCorsConfiguration(handler, request, response);
            if (config != null) {
                chain.addInterceptor(new CorsInterceptor(config));
            }
        }
        
        return chain;
    }
    
    /**
     * 构建HandlerExecutionChain
     */
    protected HandlerExecutionChain getHandlerExecutionChain(
            Object handler, HttpServletRequest request) {
        
        HandlerExecutionChain chain = 
            (handler instanceof HandlerExecutionChain existingChain ? 
                existingChain : new HandlerExecutionChain(handler));
        
        // 添加URL匹配的拦截器
        String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
        for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
            if (interceptor instanceof MappedInterceptor mappedInterceptor) {
                if (mappedInterceptor.matches(lookupPath, 
                        this.pathPatternParser != null ? null : getPathMatcher())) {
                    chain.addInterceptor(mappedInterceptor.getInterceptor());
                }
            } else {
                chain.addInterceptor(interceptor);
            }
        }
        
        return chain;
    }
}

4.4 RequestMappingHandlerMapping源码

这是最常用的HandlerMapping,负责解析@RequestMapping注解:

java 复制代码
// org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
public class RequestMappingHandlerMapping extends AbstractHandlerMethodMapping
        <RequestMappingInfo> {
    
    private boolean useSuffixPatternMatch = true;
    private boolean useTrailingSlashMatch = true;
    
    @Override
    public void afterPropertiesSet() {
        super.afterPropertiesSet();
        
        if (this.useSuffixPatternMatch) {
            this.config.setSuffixPatternMatch(true);
        }
        if (this.useTrailingSlashMatch) {
            this.config.setTrailingSlashMatch(true);
        }
    }
    
    @Override
    protected RequestMappingInfo getMappingForMethod(Method method, 
                                                     Class<?> handlerType) {
        RequestMappingInfo info = createRequestMappingInfo(method);
        if (info == null) {
            return null;
        }
        
        // 合并类级别的@RequestMapping
        RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);
        if (typeInfo != null) {
            info = typeInfo.combine(info);
        }
        
        // 添加路径前缀
        String prefix = getPathPrefix(handlerType);
        if (prefix != null) {
            info = RequestMappingInfo.paths(prefix).options(config).build()
                .combine(info);
        }
        
        return info;
    }
}

4.5 AbstractHandlerMethodMapping查找流程

java 复制代码
// org.springframework.web.servlet.handler.AbstractHandlerMethodMapping
public abstract class AbstractHandlerMethodMapping<T> extends 
        AbstractHandlerMapping implements InitializingBean {
    
    // 保存所有映射关系: RequestMappingInfo -> HandlerMethod
    private final Map<T, HandlerMethod> handlerMethods = new LinkedHashMap<>();
    
    // URL路径到RequestMappingInfo的映射(用于快速查找)
    private final MultiValueMap<String, T> urlMap = new LinkedMultiValueMap<>();
    
    @Override
    public void afterPropertiesSet() {
        initHandlerMethods();
    }
    
    /**
     * 初始化所有Handler方法
     */
    protected void initHandlerMethods() {
        for (String beanName : getCandidateBeanNames()) {
            if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
                processCandidateBean(beanName);
            }
        }
        handlerMethodsInitialized(getHandlerMethods());
    }
    
    protected void processCandidateBean(String beanName) {
        Class<?> beanType = obtainApplicationContext().getType(beanName);
        
        if (beanType == null || 
            !AnnotationUtils.findAnnotation(beanType, Controller.class) != null && 
            !AnnotationUtils.findAnnotation(beanType, RestController.class) != null) {
            return;
        }
        
        detectHandlerMethods(beanName);
    }
    
    /**
     * 检测并注册Handler方法
     */
    protected void detectHandlerMethods(Object handler) {
        Class<?> handlerType = (handler instanceof String ?
            obtainApplicationContext().getType((String) handler) : handler.getClass());
        
        Class<?> userType = ClassUtils.getUserClass(handlerType);
        
        for (Method method : getCandidateHookedMethods(userType)) {
            try {
                T mapping = getMappingForMethod(method, userType);
                if (mapping != null) {
                    registerHandlerMethod(handler, method, mapping);
                }
            } catch (Throwable ex) {
                throw new BeanInitializationException("Failed to process: " + handlerName, ex);
            }
        }
    }
    
    @Override
    protected HandlerMethod getHandlerInternal(HttpServletRequest request) {
        String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
        
        this.mappingRegistry.acquireReadLock();
        try {
            HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
            return (handlerMethod != null ? 
                handlerMethod.createWithResolvedBean() : null);
        } finally {
            this.mappingRegistry.releaseReadLock();
        }
    }
    
    /**
     * 查找匹配的HandlerMethod
     */
    protected HandlerMethod lookupHandlerMethod(String lookupPath,
                                               HttpServletRequest request) {
        List<Match> matches = new ArrayList<>();
        
        // 1. 直接路径匹配
        List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
        if (directPathMatches != null) {
            addMatchingMappings(directPathMatches, matches, request);
        }
        
        // 2. 模式匹配
        if (matches.isEmpty()) {
            addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
        }
        
        // 3. 选择最佳匹配
        if (!matches.isEmpty()) {
            Comparator<Match> comparator = getMatchingComparator(request);
            matches.sort(comparator);
            
            Match bestMatch = matches.get(0);
            
            // 检查是否有多个同分匹配
            if (matches.size() > 1) {
                Match bestMatchSecond = matches.get(1);
                if (comparator.compare(bestMatch, bestMatchSecond) == 0) {
                    Method m1 = bestMatch.handlerMethod.getMethod();
                    Method m2 = bestMatchSecond.handlerMethod.getMethod();
                    throw new IllegalStateException(
                        "Ambiguous handler methods mapped: " + m1 + " and " + m2);
                }
            }
            
            request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod);
            request.setAttribute(BEST_MATCHING_PATTERN_ATTRIBUTE, bestMatch.pattern);
            
            // 提取路径变量
            if (bestMatch.pattern.isPattern()) {
                String pattern = bestMatch.pattern.getPatternsCondition()
                    .getPatterns().iterator().next();
                Map<String, String> uriVariables = 
                    bestMatch.pattern.extractUriTemplateVariables(pattern, 
                        PathContainer.parseRequestPath(lookupPath));
                request.setAttribute(URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriVariables);
            }
            
            return bestMatch.handlerMethod;
        }
        
        return null;
    }
}

4.6 查找流程图



getHandler
遍历handlerMappings
handlerMapping.getHandler方法
返回HandlerExecutionChain?
包装拦截器
返回mappedHandler
遍历结束
返回null → 404

4.7 @RequestMapping映射合并规则

类: value=/api
合并
类: method=GET
方法: value=/users
方法: method=POST
patterns=/api/users

methods=POST


5. SpringMVC初始化流程

5.1 DispatcherServlet初始化

java 复制代码
// org.springframework.web.servlet.HttpServletBean.init()
@Override
public final void init() throws ServletException {
    setLoadOnStartup();
    WebApplicationContext wac = initServletBean();
}

// org.springframework.web.servlet.DispatcherServlet.onRefresh()
@Override
protected void onRefresh(ApplicationContext context) {
    initStrategies(context);
}

protected void initStrategies(ApplicationContext context) {
    // 1. 初始化MultipartResolver
    initMultipartResolver(context);
    
    // 2. 初始化LocaleResolver
    initLocaleResolver(context);
    
    // 3. 初始化ThemeResolver
    initThemeResolver(context);
    
    // 4. 初始化HandlerMappings
    initHandlerMappings(context);
    
    // 5. 初始化HandlerAdapters
    initHandlerAdapters(context);
    
    // 6. 初始化HandlerExceptionResolvers
    initHandlerExceptionResolvers(context);
    
    // 7. 初始化RequestToViewNameTranslator
    initRequestToViewNameTranslator(context);
    
    // 8. 初始化ViewResolvers
    initViewResolvers(context);
    
    // 9. 初始化FlashMapManager
    initFlashMapManager(context);
}

5.2 各组件初始化源码

java 复制代码
// org.springframework.web.servlet.DispatcherServlet

/**
 * 初始化MultipartResolver
 */
private void initMultipartResolver(ApplicationContext context) {
    try {
        this.multipartResolver = context.getBean(MULTIPART_RESOLVER_BEAN_NAME, 
            MultipartResolver.class);
    } catch (NoSuchBeanDefinitionException ex) {
        // 默认不使用multipart
        this.multipartResolver = null;
    }
}

/**
 * 初始化LocaleResolver
 */
private void initLocaleResolver(ApplicationContext context) {
    try {
        this.localeResolver = context.getBean(LOCALE_RESOLVER_BEAN_NAME, 
            LocaleResolver.class);
    } catch (NoSuchBeanDefinitionException ex) {
        // 使用默认实现:AcceptHeaderLocaleResolver
        this.localeResolver = getDefaultStrategy(context, LocaleResolver.class);
    }
}

/**
 * 初始化ThemeResolver
 */
private void initThemeResolver(ApplicationContext context) {
    try {
        this.themeResolver = context.getBean(THEME_RESOLVER_BEAN_NAME, 
            ThemeResolver.class);
    } catch (NoSuchBeanDefinitionException ex) {
        this.themeResolver = getDefaultStrategy(context, ThemeResolver.class);
    }
}

/**
 * 初始化HandlerMappings
 */
private void initHandlerMappings(ApplicationContext context) {
    this.handlerMappings = null;
    
    if (detectAllHandlerMappings) {
        // 查找所有HandlerMapping Bean
        Map<String, HandlerMapping> matchingBeans = 
            BeanFactoryUtils.beansOfTypeIncludingAncestors(
                context, HandlerMapping.class, true, false);
        
        if (!matchingBeans.isEmpty()) {
            this.handlerMappings = new ArrayList<>(matchingBeans.values());
        }
    } else {
        // 只查找名为handlerMapping的Bean
        HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, 
            HandlerMapping.class);
        this.handlerMappings = Collections.singletonList(hm);
    }
    
    // 如果没有找到,注册默认实现
    if (this.handlerMappings == null) {
        this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
    }
    
    // 按order排序
    AnnotationAwareOrderComparator.sort(this.handlerMappings);
}

/**
 * 初始化HandlerAdapters
 */
private void initHandlerAdapters(ApplicationContext context) {
    this.handlerAdapters = null;
    
    if (detectAllHandlerAdapters) {
        Map<String, HandlerAdapter> matchingBeans = 
            BeanFactoryUtils.beansOfTypeIncludingAncestors(
                context, HandlerAdapter.class, true, false);
        
        if (!matchingBeans.isEmpty()) {
            this.handlerAdapters = new ArrayList<>(matchingBeans.values());
        }
    } else {
        HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, 
            HandlerAdapter.class);
        this.handlerAdapters = Collections.singletonList(ha);
    }
    
    if (this.handlerAdapters == null) {
        this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
    }
}

/**
 * 初始化HandlerExceptionResolvers
 */
private void initHandlerExceptionResolvers(ApplicationContext context) {
    this.handlerExceptionResolvers = null;
    
    if (detectAllHandlerExceptionResolvers) {
        Map<String, HandlerExceptionResolver> matchingBeans = 
            BeanFactoryUtils.beansOfTypeIncludingAncestors(
                context, HandlerExceptionResolver.class, true, false);
        
        if (!matchingBeans.isEmpty()) {
            this.handlerExceptionResolvers = new ArrayList<>(matchingBeans.values());
        }
    } else {
        HandlerExceptionResolver her = context.getBean(
            HANDLER_EXCEPTION_RESOLVER_BEAN_NAME, HandlerExceptionResolver.class);
        this.handlerExceptionResolvers = Collections.singletonList(her);
    }
    
    if (this.handlerExceptionResolvers == null) {
        this.handlerExceptionResolvers = getDefaultStrategies(context, 
            HandlerExceptionResolver.class);
    }
}

/**
 * 初始化ViewResolvers
 */
private void initViewResolvers(ApplicationContext context) {
    this.viewResolvers = null;
    
    if (detectAllViewResolvers) {
        Map<String, ViewResolver> matchingBeans = 
            BeanFactoryUtils.beansOfTypeIncludingAncestors(
                context, ViewResolver.class, true, false);
        
        if (!matchingBeans.isEmpty()) {
            this.viewResolvers = new ArrayList<>(matchingBeans.values());
        }
    } else {
        ViewResolver vr = context.getBean(DEFAULT_VIEW_RESOLVER_BEAN_NAME, 
            ViewResolver.class);
        this.viewResolvers = Collections.singletonList(vr);
    }
    
    if (this.viewResolvers == null) {
        this.viewResolvers = getDefaultStrategies(context, ViewResolver.class);
    }
    
    AnnotationAwareOrderComparator.sort(this.viewResolvers);
}

/**
 * 获取默认策略
 */
protected <T> List<T> getDefaultStrategies(ApplicationContext context, 
                                          Class<T> strategyInterface) {
    List<T> strategies = new ArrayList<>();
    
    // 从DispatcherServlet.properties读取默认实现类名
    String factoryPath = DEFAULT_STRATEGIES_PATH;
    PropertiesLoader-pl
    try {
        Properties defaults = PropertiesLoaderUtils.loadProperties(
            new ClassPathResource(factoryPath));
        String value = defaults.getProperty(strategyInterface.getName());
        
        if (value != null) {
            String[] classNames = StringUtils.trimArrayElements(
                StringUtils.commaDelimitedListToStringArray(value));
            
            for (String className : classNames) {
                Class<?> clazz = ClassUtils.forName(className, 
                    DispatcherServlet.class.getClassLoader());
                Object strategy = createDefaultStrategy(context, clazz);
                strategies.add((T) strategy);
            }
        }
    } catch (Exception ex) {
        throw new BeanInitializationException("...");
    }
    
    return strategies;
}

/**
 * 创建默认策略实例
 */
protected <T> T createDefaultStrategy(ApplicationContext context, Class<T> clazz) {
    return clazz.getDeclaredConstructor().newInstance();
}

5.3 DispatcherServlet.properties默认配置

SpringMVC的默认策略配置:

properties 复制代码
# DispatcherServlet.properties
org.springframework.web.servlet.HandlerMapping=
  org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,
  org.springframework.web.servlet.controller.annotation.RequestMappingHandlerMapping

org.springframework.web.servlet.HandlerAdapter=
  org.springframework.web.servlet.MvcUriDiscoverer,
  org.springframework.web.servlet.function.support.HandlerFunctionAdapter,
  org.springframework.web.servlet.handler.SimpleControllerHandlerAdapter,
  org.springframework.web.servlet.handler.AbstractHandlerMethodAdapter

org.springframework.web.servlet.HandlerExceptionResolver=
  org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,
  org.springframework.web.servlet.mvc.method.annotation.ResponseStatusExceptionResolver,
  org.springframework.web.servlet.handler.SimpleMappingExceptionResolver

org.springframework.web.servlet.ViewResolver=
  org.springframework.web.servlet.view.InternalResourceViewResolver

org.springframework.web.servlet.LocaleResolver=
  org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver

org.springframework.web.servlet.ThemeResolver=
  org.springframework.web.servlet.theme.FixedThemeResolver

org.springframework.web.servlet.MultipartResolver=
  org.springframework.web.multipart.support.StandardServletMultipartResolver

org.springframework.web.servlet.FlashMapManager=
  org.springframework.web.servlet.support.SessionFlashMapManager

5.4 初始化时序图

ApplicationContext DispatcherServlet Servlet容器 ApplicationContext DispatcherServlet Servlet容器 逐个初始化组件 init() 获取WebApplicationContext wac onRefresh(wac) initStrategies(wac) initMultipartResolver() initLocaleResolver() initThemeResolver() initHandlerMappings() initHandlerAdapters() initHandlerExceptionResolvers() initRequestToViewNameTranslator() initViewResolvers() initFlashMapManager() 第一个请求 doService() doDispatch()


总结

组件职责总览

组件 职责
DispatcherServlet 统一请求入口,协调各组件
HandlerMapping URL → Handler 映射

请求处理关键节点

阶段 方法 说明
1. 处理器映射 getHandler(request) 遍历HandlerMapping
2. 适配器选择 getHandlerAdapter(handler) 选择Adapter
3. 前置拦截 applyPreHandle() 正序执行拦截器
4. 处理器执行 ha.handle() 参数解析+调用+返回值处理
5. 后置拦截 applyPostHandle() 逆序执行拦截器
6. 结果处理 processDispatchResult() 异常处理+视图渲染
7. 完成回调 triggerAfterCompletion() 逆序执行afterCompletion

设计模式

  1. 前端控制器模式:DispatcherServlet作为唯一入口
  2. 策略模式:HandlerMapping支持多种实现
  3. 适配器模式:HandlerAdapter适配不同处理器
  4. 模板方法模式:DispatcherServlet定义处理骨架

下篇预告

第二篇将深入讲解HandlerAdapter处理器适配器和参数绑定机制,包括:

  • HandlerAdapter体系与适配器模式
  • 参数解析器ArgumentResolver
  • 返回值处理器ReturnValueHandler
  • 拦截器链的完整执行机制
相关推荐
ch.ju1 小时前
Java程序设计(第3版)第二章——参数(实参 形参)
java
椰猫子1 小时前
SpringMVC(SpringMVC简介、请求与响应(请求映射路径、请求参数、日期类型参数传递、响应json数据))
java·前端·数据库
海兰1 小时前
【开篇】Spring AI、OpenClaw 和Hermes
java·人工智能·spring·spring ai
bzmK1DTbd1 小时前
微服务架构设计:Spring Cloud Gateway与Nacos集成
java·spring·微服务
上弦月-编程1 小时前
指针编程:高效内存管理核心
java·数据结构·算法
罗超驿1 小时前
双指针算法经典案例:LeetCode 283. 移动零(Java详解)
java·算法·leetcode
xieliyu.1 小时前
Java手搓数据结构:栈与队列模拟实现
java·数据结构·学习
清水白石0081 小时前
深入 Python 循环引用与垃圾回收:如何应对内存管理的挑战
java·jvm·python
_Evan_Yao1 小时前
从 IP 路由到 Agent 路由:最长前缀匹配如何帮你分发任务?
java·网络·后端·网络协议·tcp/ip