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.

ZhiKe AI
ZhiKe AI
ZhiKe AI
Inside Spring MVC: How DispatcherServlet Processes Requests

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);
}
processRequest

delegates 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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Spring MVCDispatcherServletRequest HandlingFrameworkServletJava Servlet
ZhiKe AI
Written by

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.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.