DispatcherServlet 源码分析
概述
DispatcherServlet 是 Spring MVC 的核心前端控制器(Front Controller),它接收所有 HTTP 请求,并将请求分派给相应的处理器(Handler)进行处理。本文将深入分析 DispatcherServlet 的请求处理全流程,从 FrameworkServlet.service() 入口一直到 doDispatch() 的完整执行链路,同时详细解析 HandlerMapping、HandlerAdapter、ViewResolver 三大核心体系以及九大组件的初始化过程。
Spring MVC 的设计遵循 Servlet 规范,DispatcherServlet 的继承层次如下:
javax.servlet.http.HttpServlet
└─ org.springframework.web.servlet.HttpServletBean
└─ org.springframework.web.servlet.FrameworkServlet
└─ org.springframework.web.servlet.DispatcherServlet- HttpServlet:标准 Servlet,定义
doGet()、doPost()、service()等模板方法。 - HttpServletBean:将 Servlet
init-param注入到 bean 属性。 - FrameworkServlet:封装
WebApplicationContext初始化,重写service()统一转发到doService()。 - DispatcherServlet:核心分发器,实现
doService()→doDispatch()的具体请求处理逻辑。
一、FrameworkServlet.service() — 请求入口
FrameworkServlet 重写了 service() 方法:
// FrameworkServlet.java
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
if (httpMethod == HttpMethod.PATCH || httpMethod == null) {
processRequest(request, response);
} else {
super.service(request, response);
}
}关键点:PATCH 方法在 HttpServlet 中没有对应的 doPatch(),所以做了特殊处理。其他标准方法由父类分派到 doGet()/doPost() 等方法,而这些方法统一委托给 processRequest():
@Override
protected final void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
// doPost, doPut, doDelete 同理...processRequest() 核心流程
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
long startTime = System.currentTimeMillis();
Throwable failureCause = null;
// 保存线程的 LocaleContext 和 RequestAttributes,处理完成后恢复
LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
LocaleContext localeContext = buildLocaleContext(request);
RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
initContextHolders(request, localeContext, requestAttributes);
try {
doService(request, response);
} catch (ServletException | IOException ex) {
failureCause = ex; throw ex;
} catch (Throwable ex) {
failureCause = ex;
throw new NestedServletException("Request processing failed", ex);
} finally {
resetContextHolders(request, previousLocaleContext, previousAttributes);
requestAttributes.requestCompleted();
publishRequestHandledEvent(request, response, startTime, failureCause);
}
}核心作用:① 保存/恢复线程上下文,避免线程池污染;② 调用模板方法 doService();③ 发布 ServletRequestHandledEvent 事件。
二、DispatcherServlet.doService() — 前置准备
doService() 在调用核心的 doDispatch() 之前做请求属性的前置设置:
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
logRequest(request);
// 对 include 请求保存属性快照,后续恢复
Map<String, Object> attributesSnapshot = null;
if (WebUtils.isIncludeRequest(request)) {
attributesSnapshot = new HashMap<>();
Enumeration<?> attrNames = request.getAttributeNames();
while (attrNames.hasMoreElements()) {
String attrName = (String) attrNames.nextElement();
if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
attributesSnapshot.put(attrName, request.getAttribute(attrName));
}
}
}
// 暴露框架对象到 request 属性,视图模板中可直接获取
request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
// 处理 FlashMap(POST-REDIRECT-GET 参数传递)
if (this.flashMapManager != null) {
FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
if (inputFlashMap != null) {
request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
}
request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
}
try {
doDispatch(request, response);
} finally {
if (WebUtils.isIncludeRequest(request)) {
// 恢复 include 请求的属性快照
}
}
}核心工作:
- 保存 include 请求属性快照,处理完成后恢复。
- 暴露框架对象:将
WebApplicationContext、LocaleResolver、ThemeResolver等放入 request 属性,可在视图模板中直接获取。 - 处理 FlashMap:获取重定向场景下传递的
INPUT_FLASH_MAP,设置OUTPUT_FLASH_MAP供下次重定向使用。
三、doDispatch() 逐行精读
doDispatch() 是 Spring MVC 的核心方法,必须逐行精读。
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
// 第1步:检查 multipart 请求
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// 第2步:获取 HandlerExecutionChain
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// 第3步:获取 HandlerAdapter
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 第4步:Last-Modified 缓存处理
String method = request.getMethod();
boolean isGetOrHead = "GET".equals(method) || "HEAD".equals(method);
if (isGetOrHead && ha instanceof LastModified) {
long lastModified = ((LastModified) ha).getLastModified(request);
if (new ServletWebRequest(request, response).checkNotModified(lastModified)) {
return; // 304 Not Modified
}
}
// 第5步:执行前置拦截器
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 第6步:HandlerAdapter 执行 Handler(真正调用 Controller 方法)
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
// 第7步:设置默认视图名(如果 Controller 未指定)
applyDefaultViewName(processedRequest, mv);
// 第8步:执行后置拦截器
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception ex) {
dispatchException = ex;
} catch (Throwable err) {
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
// 第9步:处理结果(视图解析 + 渲染)
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
} catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
throw ex;
} catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
throw err;
} finally {
// 第10步:清理资源
if (asyncManager.isConcurrentHandlingStarted()) {
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
} else if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}第1步:checkMultipart() — multipart 检测
protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {
if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {
if (WebUtils.isMultipartRequest(request)) {
return request;
}
return this.multipartResolver.resolveMultipart(request);
}
return request;
}如果配置了 MultipartResolver 且请求是 multipart/form-data 类型,则将原始 HttpServletRequest 包装为 MultipartHttpServletRequest。processedRequest 可能与原始 request 不是同一对象,finally 块中根据 multipartRequestParsed 标志清理临时文件。
第2步:getHandler() — 查找 Handler
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
for (HandlerMapping mapping : this.handlerMappings) {
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}遍历 handlerMappings(有序列表),第一个匹配就返回——HandlerMapping 的顺序决定优先级。HandlerExecutionChain 包含 Handler 对象和拦截器链。未找到时返回 404。
第3步:getHandlerAdapter() — 查找适配器
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
for (HandlerAdapter adapter : this.handlerAdapters) {
if (adapter.supports(handler)) {
return adapter;
}
}
}
throw new ServletException("No adapter for handler [...]");
}适配器模式的应用——不同 Handler 类型需不同 Adapter 驱动:
| Handler 类型 | HandlerAdapter 类型 |
|---|---|
@RequestMapping 方法 | RequestMappingHandlerAdapter |
Controller 接口 | SimpleControllerHandlerAdapter |
HttpRequestHandler | HttpRequestHandlerAdapter |
HandlerFunction | HandlerFunctionAdapter |
第4步:Last-Modified 缓存
GET/HEAD 请求检查 Handler 是否支持 LastModified 接口。若资源未变更,直接返回 304,不执行业务逻辑。
第5步:applyPreHandle() — 前置拦截器
// HandlerExecutionChain.java
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
if (getInterceptors() != null) {
for (int i = 0; i < getInterceptors().length; i++) {
HandlerInterceptor interceptor = getInterceptors()[i];
if (!interceptor.preHandle(request, response, this.handler)) {
triggerAfterCompletion(request, response, null);
return false;
}
this.interceptorIndex = i;
}
}
return true;
}按正序执行 preHandle()。任一返回 false 则中止,已执行过的拦截器的 afterCompletion() 被触发。interceptorIndex 记录已通过的拦截器数量。
第6步:ha.handle() — 执行 Controller
以 RequestMappingHandlerAdapter 为例,内部流程:
handle()
└─ invokeHandlerMethod()
├─ 创建 ServletInvocableHandlerMethod
├─ 设置参数解析器(HandlerMethodArgumentResolver)
├─ 设置返回值处理器(HandlerMethodReturnValueHandler)
└─ invokeAndHandle()
├─ 遍历参数解析器解析方法参数
├─ 反射调用目标 Controller 方法
└─ 通过返回值处理器处理返回值 → ModelAndView第7步:applyDefaultViewName() — 默认视图
private void applyDefaultViewName(HttpServletRequest request, @Nullable ModelAndView mv) throws Exception {
if (mv != null && !mv.hasView()) {
String defaultViewName = getDefaultViewName(request);
if (defaultViewName != null) {
mv.setViewName(defaultViewName);
}
}
}若 ModelAndView 未设置视图,通过 RequestToViewNameTranslator 根据请求 URL 推导默认视图名。
第8步:applyPostHandle() — 后置拦截器
按逆序执行 postHandle():
preHandle 1 → 2 → 3 → 4
→ handler.handle()
postHandle 4 ← 3 ← 2 ← 1第9步:processDispatchResult() — 视图解析与渲染
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
@Nullable Exception exception) throws Exception {
boolean errorView = false;
if (exception != null) {
if (exception instanceof ModelAndViewDefiningException) {
mv = ((ModelAndViewDefiningException) exception).getModelAndView();
} else {
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
mv = processHandlerException(request, response, handler, exception);
errorView = (mv != null);
}
}
if (mv != null && !mv.wasCleared()) {
render(mv, request, response);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
}
if (mappedHandler != null) {
mappedHandler.triggerAfterCompletion(request, response, null);
}
}三件事:① 通过 HandlerExceptionResolver 链处理异常;② 调用 render() 进行视图解析和渲染;③ 触发 afterCompletion()。
render() 的内部逻辑:
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
View view;
if (mv.getViewName() != null) {
view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
} else {
view = mv.getView();
}
if (mv.getStatus() != null) {
response.setStatus(mv.getStatus().value());
}
view.render(mv.getModelInternal(), request, response);
}第10步:finally 清理
- 异步请求:不清理 multipart,通知拦截器进入异步处理。
- 同步请求:清理 multipart 上传的临时文件。
四、九大组件初始化
九大组件在 DispatcherServlet.onRefresh() 中初始化:
@Override
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context); // 1. 文件上传解析器
initLocaleResolver(context); // 2. 国际化解析器
initThemeResolver(context); // 3. 主题解析器
initHandlerMappings(context); // 4. HandlerMapping 列表
initHandlerAdapters(context); // 5. HandlerAdapter 列表
initHandlerExceptionResolvers(context); // 6. 异常解析器列表
initRequestToViewNameTranslator(context); // 7. 请求到视图名翻译器
initViewResolvers(context); // 8. ViewResolver 列表
initFlashMapManager(context); // 9. FlashMapManager
}各组件初始化详解
MultipartResolver:从容器查找名为 multipartResolver 的 bean,未定义时为 null(不支持上传)。Spring Boot 自动配置 StandardServletMultipartResolver。
private void initMultipartResolver(ApplicationContext context) {
try {
this.multipartResolver = context.getBean(
MULTIPART_RESOLVER_BEAN_NAME, MultipartResolver.class);
} catch (NoSuchBeanDefinitionException ex) {
this.multipartResolver = null;
}
}LocaleResolver:默认 AcceptHeaderLocaleResolver(根据 Accept-Language 请求头确定区域)。可替换为 SessionLocaleResolver 或 CookieLocaleResolver。
private void initLocaleResolver(ApplicationContext context) {
try {
this.localeResolver = context.getBean(
LOCALE_RESOLVER_BEAN_NAME, LocaleResolver.class);
} catch (NoSuchBeanDefinitionException ex) {
this.localeResolver = getDefaultStrategy(context, LocaleResolver.class);
}
}ThemeResolver:默认 FixedThemeResolver,可替换为 CookieThemeResolver 或 SessionThemeResolver。
HandlerMappings:detectAllHandlerMappings 默认为 true,检测容器中所有 HandlerMapping 类型 bean 并按 Ordered 排序。若未自定义,使用 DispatcherServlet.properties 中的默认策略。
HandlerAdapters:逻辑与 HandlerMappings 相同,detectAllHandlerAdapters 默认为 true。
HandlerExceptionResolvers:检测容器中所有 HandlerExceptionResolver。常见实现:
| 实现类 | 说明 |
|---|---|
ExceptionHandlerExceptionResolver | 处理 @ExceptionHandler 方法(最常用) |
ResponseStatusExceptionResolver | 处理 @ResponseStatus 注解异常 |
DefaultHandlerExceptionResolver | 处理 Spring MVC 标准异常(400/404/405 等) |
RequestToViewNameTranslator:默认 DefaultRequestToViewNameTranslator,将请求 URL 转为视图名(如 /user/list → user/list)。
ViewResolvers:检测所有 ViewResolver bean 并按 Ordered 排序。Spring Boot 默认配置 InternalResourceViewResolver、BeanNameViewResolver 和 ContentNegotiatingViewResolver。
FlashMapManager:默认 SessionFlashMapManager,适用于 POST-REDIRECT-GET 模式。
默认策略加载
protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
String key = strategyInterface.getName();
String value = defaultStrategies.getString(key);
// 通过反射实例化默认策略
}DispatcherServlet.properties 位于 spring-webmvc 包的类路径下,为每个策略接口配置了默认实现类(如 RequestMappingHandlerMapping、InternalResourceViewResolver、SessionFlashMapManager 等)。当容器中未自定义任何策略 bean 时,这些默认实现会被加载使用。
五、HandlerMapping 体系
核心接口
public interface HandlerMapping {
@Nullable
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}主要实现类
| 实现类 | 说明 |
|---|---|
RequestMappingHandlerMapping | 支持 @RequestMapping 注解,最常用 |
SimpleUrlHandlerMapping | 基于 URL 路径匹配,支持 Ant 模式 |
BeanNameUrlHandlerMapping | 将 bean 名称(以 / 开头)映射为处理器 |
RouterFunctionMapping | WebFlux 函数式编程风格 |
WelcomePageHandlerMapping | 处理欢迎页 /index.html |
RequestMappingHandlerMapping 工作原理
初始化时扫描所有 bean,查找带有 @Controller 或 @RequestMapping 的类,将请求映射信息注册到查找结构中:
@Override
protected boolean isHandler(Class<?> beanType) {
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}AbstractHandlerMethodMapping.initHandlerMethods() 遍历 bean 名称,对 isHandler() 为 true 的调用 detectHandlerMethods() 扫描方法级的 @RequestMapping 注解。
HandlerExecutionChain
public class HandlerExecutionChain {
private final Object handler;
@Nullable
private HandlerInterceptor[] interceptors;
@Nullable
private List<HandlerInterceptor> interceptorList;
private int interceptorIndex = -1;
}除了 Handler 本身,还包括应用到该请求上的所有 HandlerInterceptor(全局 + 路径匹配)。
六、HandlerAdapter 体系
核心接口
public interface HandlerAdapter {
boolean supports(Object handler);
@Nullable
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
long getLastModified(HttpServletRequest request, Object handler);
}RequestMappingHandlerAdapter 参数解析器
| 解析器 | 解析的参数 |
|---|---|
RequestParamMethodArgumentResolver | @RequestParam |
PathVariableMethodArgumentResolver | @PathVariable |
RequestHeaderMethodArgumentResolver | @RequestHeader |
RequestBodyMethodArgumentResolver | @RequestBody |
ModelAttributeMethodProcessor | @ModelAttribute |
ServletModelAttributeMethodProcessor | 复杂 Java 对象(数据绑定) |
ServletRequestMethodArgumentResolver | HttpServletRequest、HttpServletResponse 等 |
SessionStatusMethodArgumentResolver | SessionStatus |
返回值处理器
| 处理器 | 场景 |
|---|---|
ModelAndViewMethodReturnValueHandler | 返回 ModelAndView |
ModelMethodProcessor | 返回 Model |
ViewMethodReturnValueHandler | 返回 View |
ResponseBodyMethodProcessor | @ResponseBody(直接写响应体) |
ViewNameMethodReturnValueHandler | 返回视图名字符串 |
MapMethodProcessor | 返回 Map(作为模型数据) |
七、ViewResolver 体系
核心接口
public interface ViewResolver {
@Nullable
View resolveViewName(String viewName, Locale locale) throws Exception;
}主要实现类
| 实现类 | 说明 |
|---|---|
InternalResourceViewResolver | JSP 视图 |
ThymeleafViewResolver | Thymeleaf 模板 |
FreeMarkerViewResolver | FreeMarker 模板 |
BeanNameViewResolver | 视图名作为 bean 名称查找 View |
ContentNegotiatingViewResolver | 根据 Content-Type 选择视图 |
视图解析过程
遍历 viewResolvers 列表,遍历 + 短路策略——第一个返回非空 View 的即生效:
@Nullable
protected View resolveViewName(String viewName, @Nullable Map<String, Object> model,
Locale locale, HttpServletRequest request) throws Exception {
if (this.viewResolvers != null) {
for (ViewResolver viewResolver : this.viewResolvers) {
View view = viewResolver.resolveViewName(viewName, locale);
if (view != null) {
return view;
}
}
}
return null;
}View 接口
public interface View {
String RESPONSE_STATUS_ATTRIBUTE = View.class.getName() + ".responseStatus";
@Nullable
String getContentType();
void render(@Nullable Map<String, ?> model, HttpServletRequest request,
HttpServletResponse response) throws Exception;
}常见实现:InternalResourceView(JSP)、ThymeleafView、MappingJackson2JsonView(JSON)。
八、请求处理时序图(ASCII)
Client ServletContainer FrameworkServlet DispatcherServlet HandlerMapping HandlerInterceptor HandlerAdapter ViewResolver
│ │ │ │ │ │ │ │
│── HTTP Req ──→│ │ │ │ │ │ │
│ │── service() ─────→│ │ │ │ │ │
│ │ │── processRequest() │ │ │ │ │
│ │ │── doService() ────→│ │ │ │ │
│ │ │ │── doDispatch() │ │ │ │
│ │ │ │── checkMultipart │ │ │ │
│ │ │ │── getHandler() ─→│ │ │ │
│ │ │ │ │ │── getHandler() │ │ │
│ │ │ │ │←─ HandlerExectionChain ─│ │ │
│ │ │ │── getHandlerAdapter() ─── supports() ─→│ │
│ │ │ │ │←────────────────────────────────────── HandlerAdapter │ │
│ │ │ │── applyPreHandle() ─→│ │ │ │
│ │ │ │ │ │── preHandle() ─────→│ │ │
│ │ │ │── ha.handle() ────│ │ │ │
│ │ │ │ │ │ │── handle() ──────→│ │
│ │ │ │ │ │ │ 解析参数/反射调用 │ │
│ │ │ │ │ │ │←── ModelAndView ──│ │
│ │ │ │── applyPostHandle()─→│ │ │ │
│ │ │ │ │ │── postHandle() ───→│ │ │
│ │ │ │── processDispatchResult() │ │
│ │ │ │ │── resolveViewName() ──────────────────────────────────────────────→│
│ │ │ │ │←─────────────────────────────────────────────────────────── View ──│
│ │ │ │ │── view.render() →(写入响应) │
│ │ │ │── triggerAfterCompletion() ─→│ │ │ │
│ │ │ │── cleanupMultipart() │ │── afterCompletion │ │ │
│ │ │←── 响应返回 ──────│ │ │ │ │
│←── HTTP Resp ─│ │ │ │ │ │ │九、总结
完整调用链
HttpServlet.service()
└─ FrameworkServlet.service() [PATCH 特殊处理]
└─ FrameworkServlet.processRequest()
├─ 保存/恢复 LocaleContext 和 RequestAttributes
├─ DispatcherServlet.doService()
│ ├─ 暴露框架对象到 request 属性
│ ├─ 处理 FlashMap
│ └─ DispatcherServlet.doDispatch() ← 核心
│ ├─ checkMultipart() 检测文件上传
│ ├─ getHandler() 遍历 HandlerMapping
│ ├─ getHandlerAdapter() 获取适配器
│ ├─ Last-Modified 缓存验证
│ ├─ applyPreHandle() 前置拦截器
│ ├─ ha.handle() 执行 Controller
│ ├─ applyDefaultViewName() 默认视图名
│ ├─ applyPostHandle() 后置拦截器
│ └─ processDispatchResult() 异常处理 + 视图解析 + 渲染
│ ├─ processHandlerException() 异常解析
│ ├─ render() 视图渲染
│ └─ triggerAfterCompletion() 拦截器完成回调
└─ 发布 ServletRequestHandledEvent设计模式应用
| 模式 | 体现 |
|---|---|
| 前端控制器 | DispatcherServlet 统一请求入口 |
| 策略模式 | 九大组件可替换实现 |
| 适配器模式 | HandlerAdapter 适配不同 Handler 类型 |
| 模板方法模式 | doService() → doDispatch() 模板结构 |
| 责任链模式 | HandlerInterceptor 链、HandlerExceptionResolver 链 |
| 组合模式 | HandlerExecutionChain 组合 Handler + 拦截器 |
关键知识点
DispatcherServlet是一个 Servlet,遵循标准 Servlet 生命周期。FrameworkServlet.service()是请求入口,对 PATCH 方法特殊处理。doDispatch()是核心方法,包含 10 个步骤。- 九大组件在
onRefresh()中初始化,均可自定义替换。 - HandlerMapping 顺序决定优先级,第一个匹配生效。
- HandlerAdapter 通过
supports()判断适用性,适配不同 Handler。 - ViewResolver 链式解析,名称到 View 的转换由具体实现完成。
- 拦截器执行顺序:
preHandle正序 →postHandle逆序 →afterCompletion逆序。 DispatcherServlet.properties提供默认策略,无自定义配置时框架仍可工作。