ArchitectMind
  1. Home
  2. Tutorials
  3. Book 4 · Spring & Spring Boot
  4. Volume IV
  5. DispatcherServlet
Book 4 · Volume IV — Spring MVC, REST & Web Applications · Topic 1.2

DispatcherServlet

Front controller, request routing, handler selection and response processing

9 min readStage 2 · Frameworks & design8 interview questions
Chapter
Chapter 1 — Spring MVC Architecture
Prerequisites
Topic 1.1; Volume III Chapter 7 (embedded servers)
You will be able to
Explain the DispatcherServlet's role and strategy beans, how it routes requests and selects handlers, and how it processes responses and errors
Covers
Front Controller · Request Routing · Handler Selection · Response Processing
On this page
  1. 1. Concept / Definition
  2. 2. Why It Exists
  3. 3. Core Concepts
  4. 4. How It Works Internally
  5. 4A. Deep Dive — Customising the Front Controller the Right Way
  6. 5. APIs / Features / Syntax
  7. 6. Practical Examples
  8. 7. Common Problems & Mistakes
  9. 8. Performance & Production Considerations
  10. 9. Architecture & Design Considerations
  11. 10. Interview Questions & Answers

1Concept / Definition

The DispatcherServlet is Spring MVC's front controller: a single jakarta.servlet.Servlet that receives every request for the application (mapped to /), finds the right handler, invokes it through an adapter, and produces the response — delegating each step to pluggable strategy beans from the Spring application context.

DispatcherServlet as front controller
Figure 1 — DispatcherServlet as front controller
Strategy beanRoleBoot default (servlet stack)
HandlerMappingFind handler + interceptors for a requestRequestMappingHandlerMapping, RouterFunctionMapping, welcome-page and resource mappings
HandlerAdapterInvoke a handler of a given typeRequestMappingHandlerAdapter, HandlerFunctionAdapter, …
HandlerExceptionResolverTurn exceptions into responsesException handler, response status and default resolvers
ViewResolverMap view names to viewsContentNegotiatingViewResolver, template resolvers when present
LocaleResolver, FlashMapManager, RequestToViewNameTranslatorLocale, flash attributes, default view namesAccept-header locale, session flash map
Table 1 — DispatcherServlet strategy beans

2Why It Exists

Plain servlet applications mapped one servlet per URL pattern and repeated cross-cutting logic in each. The front controller pattern centralises request handling: one component applies common processing (locale, multipart, exception handling, view rendering) and dispatches to fine-grained handlers. Spring's design goes further by making every step a strategy interface, so the same DispatcherServlet supports annotated controllers, functional endpoints, static resources and legacy handler types.

3Core Concepts

3.1 Front Controller

DispatcherServlet special beans
Figure 2 — DispatcherServlet special beans

In Spring Boot, DispatcherServletAutoConfiguration creates the servlet as a bean and registers it with the embedded server at path / (configurable with spring.mvc.servlet.path). It shares the application context with the rest of the application (Boot uses a single context rather than the classic root/servlet hierarchy).

3.2 Request Routing

Routing is layered:

LayerDecides
Servlet containerWhich servlet: filters + DispatcherServlet mapped to /
Servlet filtersWhether the request proceeds (security, CORS, encoding)
DispatcherServletWhich handler, via ordered HandlerMappings
RequestMappingInfo conditionsWhich controller method (path, method, params, headers, media types, version)
Table 2 — Routing layers
TEXT
DEBUG o.s.web.servlet.DispatcherServlet : GET "/api/orders/o-17", parameters={}
DEBUG s.w.s.m.m.a.RequestMappingHandlerMapping :
      Mapped to com.acme.OrderApiController#find(String)
DEBUG o.s.w.s.m.m.a.HttpEntityMethodProcessor : Using 'application/json', given [*/*]
DEBUG o.s.web.servlet.DispatcherServlet : Completed 200 OK

3.3 Handler Selection

Ordered handler mappings
Figure 3 — Ordered handler mappings

getHandler(request) asks each HandlerMapping in order (annotated controllers first, static resources last); the first non-null HandlerExecutionChain wins. The chain contains the handler (e.g. HandlerMethod) and the HandlerInterceptors that apply to it. If no mapping matches, Spring MVC produces a 404 (NoHandlerFoundException, handled by default in Boot as a Problem Detail or error page).

getHandlerAdapter(handler) then asks each HandlerAdapter whether it supports(handler) — decoupling the dispatcher from handler types.

3.4 Response Processing

Two response paths
Figure 4 — Two response paths
Handler resultProcessing
ModelAndView with view nameViewResolver → View.render()
Body already written (@ResponseBody, ResponseEntity)Return value handler used a message converter; no view
Async result (CompletableFuture, DeferredResult)Request put into async mode; dispatched again when complete
ExceptionHandlerExceptionResolvers → error response or error view
Table 3 — Response processing paths

4How It Works Internally

1. FrameworkServlet.service() → processRequest() sets up LocaleContextHolder and RequestContextHolder, then calls DispatcherServlet.doService().

2. doService() exposes framework attributes (context, locale resolver, flash map) on the request and calls doDispatch().

3. doDispatch(): check multipart → getHandler → getHandlerAdapter → HTTP caching check (Last-Modified) → interceptors' preHandle → ha.handle() → default view name → postHandle → processDispatchResult (render or resolve exception) → afterCompletion.

4. Strategies are initialised at start-up (initStrategies) from beans in the context, falling back to defaults in DispatcherServlet.properties when none are defined (Boot defines them).

5. After processing, request-scoped resources are cleaned up and a ServletRequestHandledEvent may be published.

4ADeep Dive — Customising the Front Controller the Right Way

NeedRight extension point
Add a custom mapping styleRegister a HandlerMapping bean (with order)
Support a new handler typeRegister a HandlerAdapter bean
Cross-cutting pre/post logic for handlersHandlerInterceptor via WebMvcConfigurer.addInterceptors
Request-level logic before Spring MVCServlet Filter / OncePerRequestFilter
Global exception mapping@ControllerAdvice or HandlerExceptionResolver bean
Change servlet path, load-on-startupspring.mvc.servlet.path, spring.mvc.servlet.load-on-startup
Tweak MVC defaults without losing BootImplement WebMvcConfigurer (without @EnableWebMvc)
Table 4 — Customisation options
JAVA
@Configuration
class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new TenantInterceptor()).addPathPatterns("/api/**");
    }
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        configurer.addPathPrefix("/api",
                HandlerTypePredicate.forAnnotation(RestController.class));
    }
}

5APIs / Features / Syntax

API / propertyPurpose
DispatcherServlet, FrameworkServletFront controller classes
HandlerMapping, HandlerExecutionChainHandler lookup
HandlerAdapterHandler invocation
HandlerInterceptorPre/post handler hooks
HandlerExceptionResolverException to response
ViewResolver, ViewRendering
WebMvcConfigurerCustomisation callbacks
spring.mvc.servlet.path, spring.mvc.servlet.load-on-startupServlet registration
logging.level.org.springframework.web=DEBUGTrace dispatching
Table 5 — DispatcherServlet APIs

6Practical Examples

6.1 Handler interceptor for timing

JAVA
class TimingInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest req, HttpServletResponse res,
                             Object handler) {
        req.setAttribute("start", System.nanoTime());
        return true;                                          // false = stop processing
    }
    @Override
    public void afterCompletion(HttpServletRequest req, HttpServletResponse res,
                                Object handler, Exception ex) {
        long ms = (System.nanoTime() - (long) req.getAttribute("start")) / 1_000_000;
        log.info("{} {} → {} in {} ms", req.getMethod(), req.getRequestURI(),
                 res.getStatus(), ms);
    }
}

6.2 Functional endpoint alongside annotated controllers

JAVA
@Bean
RouterFunction<ServerResponse> healthRoutes() {
    return RouterFunctions.route()
            .GET("/ping", req -> ServerResponse.ok().body("pong"))
            .build();  // served via RouterFunctionMapping
}

6.3 Load on start-up

YAML
spring:
  mvc:
    servlet:
      # initialise DispatcherServlet at start-up, not on first request
      load-on-startup: 1

6.4 Inspecting mappings at runtime

BASH
curl -s localhost:9090/actuator/mappings | jq '.contexts[].mappings.dispatcherServlets
  .dispatcherServlet | length'

6.5 Typical handler mapping order in a Boot MVC app

PrecedenceMappingHandles
Highest (order 0)RequestMappingHandlerMapping@RequestMapping methods
MiddleView controllers, BeanNameUrlHandlerMapping, RouterFunctionMapping, welcome pageSimple view mappings, bean-named handlers, functional endpoints, / → index.html
LowestSimpleUrlHandlerMapping for resources/** static resources from classpath:/static/ etc.
Table 6 — Why static files never shadow your controllers

Because resource handling has the lowest precedence, an @GetMapping("/app.js") wins over static/app.js, and unmatched paths fall through to static resources before resulting in 404.

6.6 Error dispatch

TEXT
Controller throws → exception resolvers produce no response
→ container forwards to /error (ERROR dispatch)
→ DispatcherServlet handles /error → BasicErrorController (JSON or HTML)

The DispatcherServlet processes the error dispatch like a normal request, which is why filters registered only for REQUEST dispatch do not run for errors.

7Common Problems & Mistakes

  • @EnableWebMvc in Boot apps — defaults disappear.
  • Filters vs interceptors confusion — security belongs in filters (before MVC), handler-specific logic in interceptors.
  • First-request latency because the DispatcherServlet initialises lazily — set load-on-startup.
  • Ambiguous mappings discovered only at start-up — keep URL spaces cohesive per controller.
  • Custom HandlerMapping without order — unexpected precedence.

These mistakes have recognisable symptoms. Ambiguous mappings fail start-up with an IllegalStateException naming both controller methods, which is good, but overlapping path patterns such as /orders/{id} and /orders/export are resolved silently by specificity, so check the Actuator mappings endpoint when a request reaches the wrong method. Interceptors have their own contract: if preHandle returns false, the interceptor must write the response itself, otherwise the client receives an empty 200; afterCompletion runs only for interceptors whose preHandle returned true; and for async handlers postHandle runs only after the async result completes, so use AsyncHandlerInterceptor for per-request clean-up. Interceptors also apply to static resource handlers unless you add excludePathPatterns, and they never run for requests rejected earlier by Spring Security's filters, so a 401 never appears in interceptor-based metrics.

8Performance & Production Considerations

ConcernGuidance
Dispatch overheadMicroseconds; mapping lookup is indexed and cached
InterceptorsRun on every matched request — keep them cheap
LoggingDEBUG on org.springframework.web is verbose; use only for diagnosis
Observabilityhttp.server.requests timers cover the whole dispatch
Table 7 — Production guidance

9Architecture & Design Considerations

  • Extend through strategies and configurers, keeping Boot's defaults.
  • Separate filter-level concerns (security, CORS, request ids) from handler-level ones.
  • Consistent URL prefixes (/api) configured centrally.
  • Functional endpoints for lightweight or programmatically composed routes; annotated controllers for most APIs.

10Interview Questions & Answers

Q1BasicConcept

What is the DispatcherServlet?

The DispatcherServlet is Spring MVC's front controller: a single jakarta.servlet.Servlet, normally mapped to /, that receives every request for the application and coordinates its handling. It does not contain business logic or routing decisions itself. For each request it asks HandlerMapping beans which handler applies, uses a HandlerAdapter to invoke it, lets HandlerExceptionResolvers turn exceptions into responses, and uses ViewResolvers when a view must be rendered. All these strategies are beans from the Spring context, which is why annotated controllers, functional endpoints and static resources can coexist behind one servlet. In Spring Boot it is created by DispatcherServletAutoConfiguration and registered with the embedded server; you rarely declare it yourself.

Q2BasicConcept

Which strategy finds the controller method for a request?

A HandlerMapping finds the handler, and for annotated controllers it is RequestMappingHandlerMapping. At start-up it scans beans annotated with @Controller, reads each @RequestMapping, @GetMapping or similar annotation and registers a RequestMappingInfo combining the path pattern, HTTP method, parameters, headers, consumes and produces media types and, in Framework 7, the API version. At request time it collects every mapping whose conditions match, chooses the most specific one and returns a HandlerExecutionChain holding the HandlerMethod plus the applicable interceptors. If two mappings are equally specific, start-up fails with an ambiguous-mapping error. The DispatcherServlet asks all HandlerMappings in order, so functional routes and static resources are found by other mappings.

Q3IntermediateInternals

Why does the DispatcherServlet use HandlerAdapters?

Because the DispatcherServlet must invoke handlers of very different types without knowing any of them. A handler might be a HandlerMethod on an annotated controller, a HandlerFunction from a RouterFunction, a legacy Controller implementation or an HttpRequestHandler serving resources. For each handler, the dispatcher asks its HandlerAdapters which one supports it, then calls adapter.handle(). RequestMappingHandlerAdapter does the heavy lifting for annotated controllers: resolving arguments such as @PathVariable and @RequestBody, data binding and validation, invoking the method and processing the return value through message converters. This is the adapter pattern applied to dispatching, and it is why a new programming model like functional endpoints could be added without changing the DispatcherServlet itself.

Q4IntermediateTrade-off

What is the difference between a servlet filter and a handler interceptor?

A servlet filter is part of the servlet container's chain and runs before the DispatcherServlet, for every request matching its URL pattern, including static resources and requests that will never reach a controller. It works only with the raw request and response, can wrap them, and can stop the chain entirely. Spring Security, CORS, character encoding and request-id propagation belong there. A HandlerInterceptor runs inside Spring MVC, after the handler has been selected, so it knows which controller method will be invoked, can inspect its annotations, and has preHandle, postHandle and afterCompletion callbacks. Choose a filter for protocol-level or security concerns, and an interceptor for logic that depends on the handler.

Q5Senior EngineerInternals

Describe doDispatch().

doDispatch() is the core algorithm. It first checks for a multipart request and wraps it if needed. It then calls getHandler(), iterating the HandlerMappings until one returns a HandlerExecutionChain; if none does, it produces a 404. Next it finds a HandlerAdapter that supports the handler, performs the Last-Modified check for GET and HEAD, and runs each interceptor's preHandle, stopping if any returns false. It invokes ha.handle(), returns early if async processing started, applies a default view name and runs postHandle. processDispatchResult() then either resolves an exception through the HandlerExceptionResolvers or renders the view. Finally afterCompletion runs for the interceptors, and multipart resources are cleaned up.

Q6Senior EngineerTricky

What happens if you add @EnableWebMvc to a Spring Boot application?

@EnableWebMvc imports DelegatingWebMvcConfiguration, which registers a WebMvcConfigurationSupport bean, and Boot's WebMvcAutoConfiguration is conditional on that bean being missing, so it backs off completely. The application still works, but Boot's customisations disappear: message converters configured from Boot's ObjectMapper and properties, static resource handling from classpath:/static, the welcome page, spring.mvc properties, format settings and parts of the error-handling integration. Symptoms appear as changed JSON date formats, missing static files or ignored properties after someone copies an @EnableWebMvc class from a non-Boot tutorial. To customise MVC in Boot, implement WebMvcConfigurer in a normal @Configuration class without @EnableWebMvc; use the annotation only when you deliberately want to own all MVC configuration.

Q7Technical ArchitectDesign

How would you add a tenant check to all API requests?

It depends on what the check needs. If the tenant comes from the authenticated principal, such as a JWT claim, and requests without a valid tenant must be rejected before any application code runs, implement it in the security layer: an AuthorizationManager rule or a filter added to the API SecurityFilterChain after authentication. That covers every path, including static and error dispatches. If the check depends on the handler, for example only controllers annotated with @TenantScoped, use a HandlerInterceptor registered for /api paths through WebMvcConfigurer, which can read the handler method's annotations. Either way, keep the resolved tenant in a request-scoped holder, clear it after the request, and return a consistent Problem Detail on failure.

Q8Solution ArchitectDesign

Why is the strategy-based design of the DispatcherServlet important for long-lived platforms?

Because it lets the framework, and the platforms built on it, evolve without breaking applications. The DispatcherServlet holds a stable algorithm, while every decision is delegated to strategy interfaces: HandlerMapping, HandlerAdapter, HandlerExceptionResolver, ViewResolver and others. Spring has used this to add annotated controllers, async request processing, functional endpoints and, in Framework 7, API versioning, all as new strategies, while code written against older models kept working. Platform teams can do the same: contribute interceptors, exception resolvers, argument resolvers or configurers through internal starters, rather than subclassing or wrapping the servlet. Extensions written that way survive framework upgrades, can be overridden per service, and keep applications on the documented, supported extension surface.

Newsletter

Get new tutorials every week

New ArchitectMind tutorials and interview questions, once a week. No spam, unsubscribe anytime.

Almost done! Check your inbox and click the confirmation link to complete your subscription.
Keep going in Book 4

Spring & Spring Boot

Volume I · Topic 1.1

Why Spring Exists

Spring Core, IoC & Dependency Injection

Volume I · Topic 1.2

Spring Framework Architecture

Spring Core, IoC & Dependency Injection

Volume I · Topic 1.3

Spring Modules

Spring Core, IoC & Dependency Injection

Volume II · Topic 1.1

Cross-Cutting Concerns

Spring AOP, Proxies, Events & Transactions

Volume II · Topic 1.2

Why Cross-Cutting Concerns Are Difficult

Spring AOP, Proxies, Events & Transactions

Volume II · Topic 1.3

Aspect-Oriented Programming

Spring AOP, Proxies, Events & Transactions

Volume III · Topic 1.1

Why Spring Boot Exists

Spring Boot, Configuration & Application Lifecycle

Volume III · Topic 1.2

Spring Boot Architecture

Spring Boot, Configuration & Application Lifecycle

Volume III · Topic 1.3

Spring Boot vs Spring Framework

Spring Boot, Configuration & Application Lifecycle

Volume IV · Topic 1.1

MVC

Spring MVC, REST & Web Applications

Volume IV · Topic 1.3

MVC Request Lifecycle

Spring MVC, REST & Web Applications

Volume V · Topic 1.1

Repository Abstraction

Spring Data, JPA & Persistence

Volume V · Topic 1.2

Spring Data Architecture

Spring Data, JPA & Persistence

Volume V · Topic 1.3

Repository Types

Spring Data, JPA & Persistence

Volume VI · Topic 1.1

Security Architecture

Spring Security, OAuth2 & Identity

Volume VI · Topic 1.2

Security Filter Chain

Spring Security, OAuth2 & Identity

Volume VI · Topic 1.3

Security Context

Spring Security, OAuth2 & Identity

Volume VII · Topic 1.1

Enterprise Integration

Spring Integration, Testing & Cloud-Native Development

Volume VII · Topic 1.2

Integration Patterns

Spring Integration, Testing & Cloud-Native Development

Volume VII · Topic 1.3

Messaging Systems

Spring Integration, Testing & Cloud-Native Development