How a request travels through Spring MVC

Spring Boot · lesson 16 of 39 · 4 min read

Follow one HTTP request from the filter chain to your method and back out as JSON.

Open this lesson in the learning hub

Key points

  • Servlet filters run first and last: security, CORS and request logging see the request before Spring MVC does.
  • The DispatcherServlet is the front controller. It owns the request and delegates every step from there.
  • HandlerMapping turns verb plus path into one handler method; a HandlerAdapter then invokes it.
  • Arguments are resolved first: @PathVariable, @RequestParam, @RequestBody via a converter.
  • The return value goes back out through a converter, so Jackson writes the JSON after your method returns.
  • Interceptors wrap only the handler; filters wrap everything. Pick the one whose scope you actually need.

Example

// 1. A filter runs outside Spring MVC, around the whole request.
@Component
class RequestIdFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res,
                                    FilterChain chain) throws ServletException, IOException {
        MDC.put("requestId", UUID.randomUUID().toString());
        try {
            chain.doFilter(req, res);   // everything below happens inside this call
        } finally {
            MDC.clear();                // and unwinds back out to here
        }
    }
}

// 2. An interceptor runs inside the DispatcherServlet, around the handler only.
@Component
class TimingInterceptor implements HandlerInterceptor {

    private static final Logger log = LoggerFactory.getLogger(TimingInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) {
        req.setAttribute("startedAt", System.nanoTime());
        return true;                    // returning false stops the request here
    }

    @Override
    public void afterCompletion(HttpServletRequest req, HttpServletResponse res,
                                Object handler, Exception ex) {
        long ms = (System.nanoTime() - (long) req.getAttribute("startedAt")) / 1_000_000;
        log.info("handled {} in {} ms", req.getRequestURI(), ms);
    }
}

A request nests inwards through filters and the dispatcher, and the response is written on the way back out.

This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Spring Boot course, and every lesson in it is listed on the Spring Boot contents page.