Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Spring MVC Request Processing Flow

Tech May 9 4

DispatcherServlet Initialization

Spring MVC's request processing starts with the DispatcherServlet, which is configured as the front controller in web.xml. During Tomcat startup, the DispatcherServlet initializes various strategy components.

Component Initialization

The initStrategies() method initializes core components:

protected void initStrategies(ApplicationContext context) {
    initMultipartResolver(context);
    initLocaleResolver(context);
    initThemeResolver(context);
    initHandlerMappings(context);
    initHandlerAdapters(context);
    initHandlerExceptionResolvers(context);
    initRequestToViewNameTranslator(context);
    initViewResolvers(context);
    initFlashMapManager(context);
}

Request Handling Sequence

1. Request Recepsion

Tomcat receives client requests and forwards them to DispatcherServlet based on URL pattern mapping in web.xml.

2. Handler Mapping Resolution

The DispatcherServlet uses HandlerMapping to locate appropriate controllers:

mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
    noHandlerFound(processedRequest, response);
    return;
}

This returns a HandlerExecutionChain containing the target handler and interceptors.

3. Handler Adapter Selection

The framework selects a suitable HandlerAdapter:

HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

The adapter selection process iterates through available adapters:

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
    if (this.handlerAdapters != null) {
        for (HandlerAdapter adapter : this.handlerAdapters) {
            if (adapter.supports(handler)) {
                return adapter;
            }
        }
    }
    throw new ServletException("No suitable adapter found");
}

4. Handler Executino

Before executing the handler, pre-processing interceptors run:

if (!mappedHandler.applyPreHandle(processedRequest, response)) {
    return;
}

The applyPreHandle method processes all registered interceptors:

boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) {
    HandlerInterceptor[] interceptors = getInterceptors();
    if (!ObjectUtils.isEmpty(interceptors)) {
        for (int i = 0; i < interceptors.length; i++) {
            HandlerInterceptor interceptor = interceptors[i];
            if (!interceptor.preHandle(request, response, this.handler)) {
                triggerAfterCompletion(request, response, null);
                return false;
            }
            this.interceptorIndex = i;
        }
    }
    return true;
}

5. Controller Processing

The adapter executes the controller method:

mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

This returns a ModelAndView object containing both data and view information.

Response Processing

6. View Resolution

The framework resolves the logical view name to a physical view:

private void applyDefaultViewName(HttpServletRequest request, ModelAndView mv) throws Exception {
    if (mv != null && !mv.hasView()) {
        String defaultViewName = getDefaultViewName(request);
        if (defaultViewName != null) {
            mv.setViewName(defaultViewName);
        }
    }
}

7. Post-Processing Interceptors

After handler execusion, post-processing interceptors execute:

mappedHandler.applyPostHandle(processedRequest, response, mv);

8. Result Processing

The framework processes the dispatch result:

processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);

This method handles view rendering through the render() method:

protected void render(ModelAndView mv, HttpServletRequest request, 
                     HttpServletResponse response) throws Exception {
    Locale locale = (this.localeResolver != null ? 
                    this.localeResolver.resolveLocale(request) : request.getLocale());
    response.setLocale(locale);
    
    View view;
    String viewName = mv.getViewName();
    if (viewName != null) {
        view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
        if (view == null) {
            throw new ServletException("Could not resolve view");
        }
    } else {
        view = mv.getView();
        if (view == null) {
            throw new ServletException("ModelAndView contains no view");
        }
    }
    
    view.render(mv.getModelInternal(), request, response);
}

9. Completion Handling

After completion, the framework triggers completion interceptors:

void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, 
                           Exception ex) throws Exception {
    HandlerInterceptor[] interceptors = getInterceptors();
    if (!ObjectUtils.isEmpty(interceptors)) {
        for (int i = this.interceptorIndex; i >= 0; i--) {
            HandlerInterceptor interceptor = interceptors[i];
            try {
                interceptor.afterCompletion(request, response, this.handler, ex);
            } catch (Throwable ex2) {
                logger.error("Interceptor completion error", ex2);
            }
        }
    }
}

Key Architectural Components

HandlerAdapter Interface

The HandlerAdapter interface defines three core methods:

public interface HandlerAdapter {
    boolean supports(Object handler);
    ModelAndView handle(HttpServletRequest request, 
                       HttpServletResponse response, Object handler) throws Exception;
    long getLastModified(HttpServletRequest request, Object handler);
}

HandlerExecutionChain

This chain manages the execution flow through:

  • Target handler object
  • Pre-processing interceptors
  • Post-processing interceptors
  • Completion interceptors

Request Flow Summary

  1. Client request arrives at DispatcherServlet
  2. HandlerMapping identifies appropriate controller
  3. HandlerAdapter executes the controller method
  4. Pre-process interceptors execute
  5. Controller processes request and returns ModelAndView
  6. Post-process interceptors execute
  7. ViewResolver maps logical view to physical view
  8. View renders response with model data
  9. Completion interceptors execute
  10. Response returns to client

Related Articles

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

SBUS Signal Analysis and Communication Implementation Using STM32 with Fus Remote Controller

Overview In a recent project, I utilized the SBUS protocol with the Fus remote controller to control a vehicle's basic operations, including movement, lights, and mode switching. This article is aimed...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.