Hook: Think of DispatcherServlet as the front desk of a hotel: every request walks in there first, gets routed to the right room, and any problem on the way is handled in one place. Interviewers love this question because it reveals whether you understand the request flow, not just annotations.
Question: How does DispatcherServlet work?
Answer: DispatcherServlet is Spring MVC’s main entry point. It receives an HTTP request, asks the mapping system which controller method should handle it, uses the right adapter to call that method, and then writes the result back as a view or JSON response. In Spring Boot REST APIs, it is usually the piece that turns a URL like /api/users/42 into a controller method call and then serializes the returned object into JSON.
Interview-Ready Answer: “In Spring MVC, DispatcherServlet is the front controller. I see it as the traffic cop for every request: it receives the request from the servlet container, asks the handler mappings which controller should handle it, uses a handler adapter to invoke that method, and then passes the result through message converters or view rendering. For REST APIs, the important part is that it usually converts the returned object to JSON and also routes exceptions through Spring’s exception resolvers.”
DispatcherServlet is the front controller in Spring MVC. A front controller is a single entry point that receives requests and delegates them to the right handler. In Spring Boot, this servlet is auto-registered for you by default, usually mapped to /, so it can see almost every request that reaches your application.
DispatcherServlet. If the URL matches its mapping, the servlet becomes the coordinator for the rest of the request.HandlerMapping for a handler. A HandlerMapping is Spring’s lookup mechanism that finds the best controller method for the request path, HTTP method, headers, and other conditions. The common implementation in REST apps is RequestMappingHandlerMapping.HandlerAdapter. The adapter knows how to invoke that kind of handler. For annotated controllers, RequestMappingHandlerAdapter handles method arguments, validation, and return values.@Valid.@RestController or @ResponseBody tells Spring to write the return value to the HTTP response body. HttpMessageConverter objects then serialize Java objects into JSON, XML, or other formats.DispatcherServlet asks its HandlerExceptionResolver chain what to do. This is how @ExceptionHandler, @ControllerAdvice, and many built-in status mappings work.This design keeps request handling consistent. Instead of every controller parsing the HTTP request itself, Spring centralizes routing, conversion, validation, and error handling. That makes code smaller, easier to test, and easier to extend.
For REST, the servlet usually does not “do business logic.” It orchestrates. The controller is where your endpoint logic lives, while DispatcherServlet handles the plumbing around it. A good interview line is: “DispatcherServlet is the conductor; controllers are the musicians.”
| Piece | Main job | Runs when |
|---|---|---|
| Filter | Cross-cutting servlet work | Before DispatcherServlet |
| DispatcherServlet | Route and orchestrate MVC | After filters |
| Controller | Business endpoint logic | After mapping |
The servlet itself is lightweight; most time is usually spent in JSON processing, validation, databases, or downstream services. Conceptually, the work per request is close to O(k) where k is the amount of handler and resolver checking, but in real apps the cost is tiny compared with I/O. In Spring Boot 3 / Spring Framework 6, the servlet APIs use jakarta.servlet; in Boot 2 they used javax.servlet. The core idea stays the same.
Important edge cases: a path that matches no controller becomes a 404, an exception in a controller can be turned into a structured error by advice, and filters still run even if no controller is found. Also remember that @RestController is just @Controller plus @ResponseBody, so the return value is written directly to the response body instead of being treated as a view name.
Imagine a checkout service for an e-commerce app. A request like GET /api/orders/123 comes in, and DispatcherServlet routes it to OrderController. The controller fetches the order, the response is serialized into JSON, and the frontend shows the order summary. If the order ID is invalid, the controller or an advice class returns a clean 404 or 400 instead of a stack trace.
What goes wrong when people misunderstand this flow? A common outage is putting business logic in a filter or assuming every request reaches the controller. Suddenly, requests with a missing header are rejected before your controller code ever runs, or a new endpoint returns 404 because the mapping is wrong. In logs you might see filter messages but no controller logs, and users report “the API is down” even though only one path is unmapped. The fix is to know exactly where the request stops: filter, dispatcher, mapping, controller, or exception handler.
package com.example.dispatcherdemo;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.http.ProblemDetail;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.Map;
@SpringBootApplication
public class DispatcherDemoApplication {
public static void main(String[] args) {
SpringApplication.run(DispatcherDemoApplication.class, args);
}
@Configuration
static class WebConfig {
@Bean
RequestIdInterceptor requestIdInterceptor() {
return new RequestIdInterceptor();
}
@Bean
WebMvcConfigurer webMvcConfigurer(RequestIdInterceptor requestIdInterceptor) {
return new WebMvcConfigurer() {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// Interceptors run after DispatcherServlet has matched a handler
// but before the controller method executes.
registry.addInterceptor(requestIdInterceptor)
.addPathPatterns("/api/**");
}
};
}
}
static class RequestIdInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// This is a realistic edge case: block requests early if the client forgot
// a required header. DispatcherServlet will route this exception through
// Spring MVC's error handling instead of calling the controller.
String requestId = request.getHeader("X-Request-Id");
if (requestId == null || requestId.isBlank()) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Missing X-Request-Id header");
}
request.setAttribute("requestId", requestId);
return true;
}
}
@RestController
@RequestMapping("/api")
static class ApiController {
@GetMapping("/hello/{name}")
Map<String, Object> hello(@PathVariable String name, HttpServletRequest request) {
// Simulate a business failure to show how the DispatcherServlet pipeline
// hands exceptions to Spring's exception resolvers.
if ("fail".equalsIgnoreCase(name)) {
throw new IllegalStateException("Simulated business failure");
}
return Map.of(
"message", "Hello, " + name,
"requestId", request.getAttribute("requestId")
);
}
@GetMapping("/boom")
Map<String, String> boom() {
throw new IllegalStateException("Something went wrong in the controller");
}
}
@RestControllerAdvice
static class ApiErrorAdvice {
@ExceptionHandler(IllegalStateException.class)
ProblemDetail handleIllegalState(IllegalStateException ex, HttpServletRequest request) {
// A structured error is ideal for REST APIs because clients can parse it
// reliably instead of scraping a plain text message.
ProblemDetail problem = ProblemDetail.forStatus(HttpStatus.INTERNAL_SERVER_ERROR);
problem.setTitle("Controller failure");
problem.setDetail(ex.getMessage());
problem.setProperty("path", request.getRequestURI());
return problem;
}
}
}
Follow-up & Tricky Questions:
DispatcherServlet choose the right controller method? It asks the HandlerMapping chain, which checks path, HTTP method, headers, consumes/produces rules, and other conditions before picking the best match.HandlerAdapter? It is the bridge that knows how to invoke a particular handler type. For annotated controllers, it resolves method arguments, calls the method, and processes the return value.HandlerExceptionResolver implementations, which is how @ExceptionHandler, @ControllerAdvice, and many built-in status responses work.@Controller and @RestController? @RestController is @Controller plus @ResponseBody, so the return value is written to the HTTP body instead of being treated as a view name.DispatcherServlet the same as a filter? No. A filter runs before the servlet and is intended for cross-cutting request/response work, while DispatcherServlet is the MVC router and orchestrator.Common Mistakes:
DispatcherServlet is the Spring MVC front controller that sits after filters.@RestController, Spring uses message converters to write JSON directly to the body.Memory Hook: Security, dispatcher, pilot. Filters are the security gate, DispatcherServlet is the traffic controller at the front desk, and the controller is the pilot who actually flies the plane.
Cheat Sheet:
DispatcherServlet for Spring MVC.HandlerMapping.HandlerAdapter.HttpMessageConverter objects.Practice Tasks:
@RestController endpoint and return a POJO to see JSON serialization.HandlerInterceptor that rejects missing headers and observe where the request stops.@RestControllerAdvice to see the error pipeline in action.