Spring MVC Request Processing Flow
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
- Client request arrives at DispatcherServlet
- HandlerMapping identifies appropriate controller
- HandlerAdapter executes the controller method
- Pre-process interceptors execute
- Controller processes request and returns ModelAndView
- Post-process interceptors execute
- ViewResolver maps logical view to physical view
- View renders response with model data
- Completion interceptors execute
- Response returns to client