Backend Development 7 min read

How Spring MVC Processes a Request: From DispatcherServlet to ViewResolver

This article explains step‑by‑step how Spring MVC handles an incoming HTTP request, detailing the roles of DispatcherServlet, HandlerMapping, HandlerAdapter, argument and return value resolvers, and ViewResolver, and includes key code excerpts that illustrate the matching and initialization processes.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
How Spring MVC Processes a Request: From DispatcherServlet to ViewResolver

Overview

When a request arrives, Spring processes it through a series of core components.

Spring MVC Processing Flow

DispatcherServlet – entry point for all requests.

HandlerMapping – maps request URLs to handlers.

HandlerAdapter – invokes the matched handler.

HandlerMethodArgumentResolver – resolves method arguments.

HandlerMethodReturnValueHandler – processes the return value.

ViewResolver – resolves views when a ModelAndView is returned.

Getting HandlerMapping

The servlet retrieves all HandlerMapping beans from the application context.

<code>public class DispatcherServlet extends FrameworkServlet {
  private List<HandlerMapping> handlerMappings;
  private void initHandlerMappings(ApplicationContext context) {
    // Find all HandlerMapping beans, including ancestors.
    Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
    if (!matchingBeans.isEmpty()) {
      this.handlerMappings = new ArrayList<>(matchingBeans.values());
      AnnotationAwareOrderComparator.sort(this.handlerMappings);
    }
  }
}
</code>

Finding the Appropriate HandlerMapping

The servlet iterates over the retrieved HandlerMapping instances to locate one that matches the current request URI.

<code>public class DispatcherServlet extends FrameworkServlet {
  private List<HandlerMapping> handlerMappings;
  protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    HandlerExecutionChain mappedHandler = null;
    // Find a HandlerMapping that can handle the request.
    mappedHandler = getHandler(processedRequest);
  }
  protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    if (this.handlerMappings != null) {
      for (HandlerMapping mapping : this.handlerMappings) {
        HandlerExecutionChain handler = mapping.getHandler(request);
        if (handler != null) {
          return handler;
        }
      }
    }
    return null;
  }
}
</code>

Spring provides five default HandlerMapping implementations, with RequestMappingHandlerMapping being the most commonly used.

HandlerMapping Matching Logic

The matching process delegates to

AbstractHandlerMapping#getHandler

, which calls the subclass‑specific

getHandlerInternal

method.

<code>public abstract class AbstractHandlerMapping {
  public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    Object handler = getHandlerInternal(request);
    // ...
    HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
    // ...
    return executionChain;
  }
}
public abstract class AbstractHandlerMethodMapping {
  protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
    String lookupPath = initLookupPath(request);
    try {
      HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
      return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
    } catch (Exception e) {
      // ...
    }
  }
  protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
    List<Match> matches = new ArrayList<>();
    List<T> directPathMatches = this.mappingRegistry.getMappingsByDirectPath(lookupPath);
    if (!matches.isEmpty()) {
      Match bestMatch = matches.get(0);
      handleMatch(bestMatch.mapping, lookupPath, request);
      return bestMatch.getHandlerMethod();
    }
    // ...
    return null;
  }
}
</code>

Initializing HandlerMethods

After a matching HandlerMapping is found, Spring initializes all

@RequestMapping

methods.

<code>public class RequestMappingHandlerMapping {
  public void afterPropertiesSet() {
    super.afterPropertiesSet();
  }
}
public abstract class AbstractHandlerMethodMapping {
  public void afterPropertiesSet() {
    initHandlerMethods();
  }
  protected void initHandlerMethods() {
    for (String beanName : getCandidateBeanNames()) {
      if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
        processCandidateBean(beanName);
      }
    }
    handlerMethodsInitialized(getHandlerMethods());
  }
  protected void processCandidateBean(String beanName) {
    Class<?> beanType = null;
    try {
      beanType = obtainApplicationContext().getType(beanName);
    } catch (Exception e) {
      // ...
    }
    if (beanType != null && isHandler(beanType)) {
      detectHandlerMethods(beanName);
    }
  }
  protected void detectCandidateMethods(Object handler) {
    Class<?> handlerType = (handler instanceof String ? obtainApplicationContext().getType((String) handler) : handler.getClass());
    if (handlerType != null) {
      Class<?> userType = ClassUtils.getUserClass(handlerType);
      Map<Method, T> methods = MethodIntrospector.selectMethods(userType, method -> {
        try {
          return getMappingForMethod(method, userType);
        } catch (Exception e) {
          // ...
        }
      });
      methods.forEach((method, mapping) -> {
        Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
        registerHandlerMethod(handler, invocableMethod, mapping);
      });
    }
  }
  protected void registerHandlerMethod(Object handler, Method method, T mapping) {
    this.mappingRegistry.register(mapping, handler, method);
  }
  class MappingRegistry {
    public void register(T mapping, Object handler, Method method) {
      HandlerMethod handlerMethod = createHandlerMethod(handler, method);
      for (String path : directPaths) {
        this.pathLookup.add(path, mapping);
      }
    }
  }
}
</code>

That concludes the request handling flow in Spring MVC.

Spring MVCJava backendDispatcherServletHandlerMappingRequest Handling
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

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