Inside Spring MVC: How DispatcherServlet Processes Requests
The article dissects Spring MVC’s core request flow, detailing how DispatcherServlet extends HttpServlet, delegates to FrameworkServlet, and ultimately routes requests through doService, doDispatch, handler adapters, interceptors, and result processing, with code excerpts illustrating each step.
Spring MVC routes every HTTP request through DispatcherServlet . The servlet hierarchy is DispatcherServlet → FrameworkServlet → HttpServlet.
HttpServlet.service
HttpServlet implements service(HttpServletRequest req, HttpServletResponse resp) and dispatches to method‑specific handlers based on req.getMethod(). The core logic is:
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();
long lastModified;
if (method.equals("GET")) {
lastModified = this.getLastModified(req);
if (lastModified == -1L) {
this.doGet(req, resp);
} else {
long ifModifiedSince = req.getDateHeader("If-Modified-Since");
if (ifModifiedSince < lastModified) {
this.maybeSetLastModified(resp, lastModified);
this.doGet(req, resp);
} else {
resp.setStatus(304);
}
}
} else if (method.equals("HEAD")) {
// similar handling for HEAD
} else if (method.equals("POST")) {
this.doPost(req, resp);
} // … other HTTP methods
else {
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[]{method};
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(501, errMsg);
}
}FrameworkServlet
FrameworkServlet extends HttpServlet and overrides the HTTP‑method handlers to forward to processRequest:
protected final void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
} processRequestdelegates to doService:
protected void doService(HttpServletRequest request, HttpServletResponse response)
throws Exception {
// …
doDispatch(request, response);
// …
}DispatcherServlet.doDispatch
The central dispatch method performs the full request‑handling pipeline:
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 {
// multipart handling
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// handler lookup
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// handler adapter
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// last‑modified support
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
// pre‑handle interceptors
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// invoke handler
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
// post‑handle interceptors
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception ex) {
dispatchException = ex;
} catch (Throwable err) {
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
// process the result (including exception handling)
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
} catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
} catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
} finally {
if (asyncManager.isConcurrentHandlingStarted()) {
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
} else {
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}Core processing flow
Obtain the HandlerExecutionChain for the incoming request via getHandler.
Resolve the appropriate HandlerAdapter for the handler object.
Execute HandlerInterceptor.preHandle chain; abort if any returns false.
Invoke the handler through the adapter ( ha.handle), producing a ModelAndView.
If asynchronous processing starts, exit early; otherwise apply default view name.
Execute HandlerInterceptor.postHandle chain.
Delegate to processDispatchResult to render the view or handle exceptions.
After completion, run HandlerInterceptor.afterCompletion and clean up multipart resources if needed.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
ZhiKe AI
We dissect AI-era technologies, tools, and trends with a hardcore perspective. Focused on large models, agents, MCP, function calling, and hands‑on AI development. No fluff, no hype—only actionable insights, source code, and practical ideas. Get a daily dose of intelligence to simplify tech and make efficiency tangible.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
