SpringMVC请求处理流程源码解析(第1篇):请求入口与处理器映射
SpringMVC是Spring Framework提供的Web层MVC框架,其核心设计思想是"前端控制器模式"。本文深入剖析从请求入收到响应返回的完整源码流程,揭示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方法分发到doGet、doPost等方法:
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;
}
关键设计点:
- ThreadLocal模式 :通过
LocaleContextHolder和RequestContextHolder将请求上下文绑定到当前线程 - 作用域传播 :通过
RequestContextFilter可以将子线程的请求属性传播到父线程 - 事件发布 :
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 关键节点详解
- ha.handle
解析参数
调用Controller
处理返回值
返回ModelAndView - applyPreHandle
否
正序遍历
调用preHandle
返回true?
triggerAfterCompletion - getHandlerAdapter
是
否
遍历handlerAdapters
adapter.supports方法
支持?
返回HandlerAdapter
下一个 - 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 |
设计模式
- 前端控制器模式:DispatcherServlet作为唯一入口
- 策略模式:HandlerMapping支持多种实现
- 适配器模式:HandlerAdapter适配不同处理器
- 模板方法模式:DispatcherServlet定义处理骨架
下篇预告
第二篇将深入讲解HandlerAdapter处理器适配器和参数绑定机制,包括:
- HandlerAdapter体系与适配器模式
- 参数解析器ArgumentResolver
- 返回值处理器ReturnValueHandler
- 拦截器链的完整执行机制