Spring MVC – DispatcherServlet

Danae's portrait in B&W - DSC02072

Creative Commons License photo credit: greekadman

In a previous post about Spring MVC I touched briefly about the DispatcherServlet and what it means for Spring-MVC.

In this post I am going to dive a bit deeper into the the DispatcherServlet and how Spring MVC uses it.

It is probably a good idea to have a read of the previous post before you read this one, but it isn’t absolutely necessary.

Spring is a Dependency Injection (DI) framework. In short this means that Spring provides your application with someone that takes charge of feeding your Java classes with what they need (their dependencies) when they need them (at run time).
This someone is the Spring core container and the dependencies, including your own code, are normally treated as spring beans. (Don’t go and read this link – there’s a lot of information there and you don’t need it right now).
The only thing that matters in the context of this blog post, is that with Spring (and Spring MVC) – there’s a lot of magic happening all around your application and it is sometimes easy to lose track of what goes where. You’ll be fine as long as you remember the three simple rules:

  1. If you want a class to participate in DI – Spring needs to know about it.
  2. Almost everything that matters in your application is a bean inside the container
  3. Use the SEP (Somebody Else’s Problem) principle. (I’ll write about it soon, but this is mainly the idea that every class needs only to focus on the specific problem it tries to solve, and leave everything else to the container and aspects).

A quick one about Spring-MVC

(Note:The description below omits some levels of complexity on purpose, because I want to focus on the general 80/20 rule in web applications. Yes, Spring MVC can do more)

Spring MVC is part of spring-web, which means that it is part of Spring’s “web arsenal”. Additionally, this is an MVC framework. For writing web applications in general and in Spring-MVC in particular, this means that the framework expects and enforces a structure to the code: you have your views, your controllers and your models.

Views

A view is what the web browser displays to your users. Views in Spring MVC are normally coded in a flavour of decorated HTML (e.g. JSP, JSF, Tapestry etc). Whenever a user makes a request of your application, your application responds with a view, which on the user’s browser is normally made up of HTML, images and javascript.
Views can be dynamic or static. That is – the content of the view can be dynamic or static, and your spring-mvc application can cater for both possibilities.
“Static” means that the content displayed to the user does not change based on session or url parameters. For example – when a user accesses a terms-and-conditions page. The terms and conditions are not normally read from a database or otherwise depend on the user’s session. If you have a JSP page containing the Terms and Conditions – it may actually contain plain HTML content, and not require any data from the application.
“Dynamic” means that the same page displays different content, depending on the URL, the session, the user’s permissions etc. For example, if the user enters a URL like http://duckranger.com/friend?name=mickey-mouse , they will probably view the details of my friend Mickey Mouse. Visiting the same URL with another URL param – http://duckranger.com/friend?name=donald – will display the same page (that is – the same view) but with Donald’s details. This view displays dynamic content based on the URL parameter “name”.
How does this happen? Well, with –

Models

A model is the way your application treats your data. It doesn’t matter where the data comes from or how it was pulled – as far as the various objects in your application are concerned, the data is represented as a Java object (or objects) – and in Spring-MVC – this is called your Model.
Models can be used by views to display dynamic data. When the user accessed http://duckranger.com/friend?name=mickey-mouse – the application looked up my friend Mickey Mouse, and created a Model object containing Mickey’s details. The view that gets displayed back to the user receives this model, and displays the data inside it to the user. If the user requests a different name (e.g. http://duckranger.com/friend?name=donald) – then the application will create a Model containing Donald’s details. The view does not care whose details it shows – it only cares that it receives the right Models it needs.
But who supplies the view with the data (the models)? –

Controllers

The controllers receive the user request (the URL that the user enters in their browser). If the URL requires the application to perform data retrieval – that is, if the user request translates to a dynamic view – then the controller will retrieve the data, create a Model, and pass it to the view.

And so, really, the MVC idea is quite simple, but also quite powerful.
When you split your code along the M.V.C. lines, your code becomes a bit ‘cleaner’. The code that deals with presentation (the rendering of HTML and javascript to users) does not normally contain a lot of complex logic, and is therefore very easy to translate (e.g. from JSP to JSF, if you need to, but also from JSP to PDF, if you need to, or a CSV, etc, etc).
When you use a model to encapsulate your data, you can let other parts of your application use it as well. So, for example, it can be used with services that have nothing to do with controllers (or the web, for that matter) – like batch runs.

So… that DispatcherServlet

Yes, I am getting there.
In any MVC framework, incoming requests always end up serviced by some method on some controller. This means that you need some way to map those incoming requests to methods on the controllers. In CakePHP, for example, the URL is the mapping (unless you change it with specific routes and handling). So, the request for http://duckranger.com/friends/add will map to the add() method of FriendsController. Similarly, the request to http://duckranger.com/friends/edit/5 will map to the edit() method of FriendsController, and pass in the parameter ‘5’ (which in CakePHP is usually the id of the row in the database you want to edit).
This mapping is achieved by CakePHP’s Routes mechanism.

In Spring-MVC we map a little differently (you can brush up on this mapping here) but the idea is the same as with CakePHP – there is some mechanism that inspects the incoming request and decides which controller and method are going to serve it. This is the DispatcherServlet.

The first thing to remember about Spring’s DispatcherServlet is that it is an actual Servlet, as in a Java HttpServlet. It is also a Spring Bean (remember the Spring core container – that holds beans and weaves them together into an application?).
Being a Spring bean means that it lives inside Spring’s container, and has access to the container methods and data. Specifically, the DispatcherServlet is interested in the various controllers we define. The controllers, remember, are where the DispatcherServlet is sending (delegating) the users’ incoming requests – so it must be able to know about them.
Luckily – the controllers are all beans as well, living inside Spring’s container – so the DispatcherServlet can be made aware of them and use them – all courtesy of Spring. Magic!

Being an HttpServlet, Spring’s DispatcherServlet is not special as far as any servlet container or application server is concerned. This is great, because it means that you don’t need to do anything special to deploy a Spring-MVC application. All you need is a standard web.xml file that registers Spring’s DispatcherServlet with your application:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring/root-context.xml</param-value>
	</context-param>
	
	<!-- Creates the Spring Container shared by all Servlets and Filters -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- Processes application requests -->
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
		
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

</web-app>

This is the default web.xml generated by STS when you create a template Spring-MVC project. It contains more than just the DispatcherServlet definition, but all we care about for now are the following lines:

<!-- Processes application requests -->
<servlet>
	<servlet-name>appServlet</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	<init-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
	</init-param>
	<load-on-startup>1</load-on-startup>
</servlet>
		
<servlet-mapping>
	<servlet-name>appServlet</servlet-name>
	<url-pattern>/</url-pattern>
</servlet-mapping>

The <servlet> element defines the DispatcherServlet as a servlet in the servlet container, and the <servlet-mapping> element maps it to the root of your application (using the ‘/’ url-pattern).
The element is an important but not mandatory part. This is how the container feeds the DispatcherServlet with the configuration required to set it up as a Spring bean (and therefore – have access to all other Spring beans in your application, like the controllers).
But, contextConfigLocation is not mandatory because the DispatcherServlet has a default contextConfigLocation value.

Initializing the DispatcherServlet

The DispatcherServlet extends FrameworkServlet. The hierarchy looks like this:

javax.servlet.GenericServlet
              |
javax.servlet.http.HttpServlet
              |
org.springframework.web.servlet.HttpServletBean
              |
org.springframework.web.servlet.FrameworkServlet
              |
org.springframework.web.servlet.DispatcherServlet

As part of the Servlet contract, the servlet container instantiates the servlet, and then initializes it by calling its init() method.
The init() method itself is found in the GenericServlet class, but HttpServletBean overrides it. The following code is from HttpServletBean.java:

public final void init() throws ServletException {
	if (logger.isDebugEnabled()) {
		logger.debug("Initializing servlet '" + getServletName() + "'");
	}

	// Set bean properties from init parameters.
	try {
		PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
		BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
		ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
		bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, this.environment));
		initBeanWrapper(bw);
		bw.setPropertyValues(pvs, true);
	}
	catch (BeansException ex) {
		logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);
		throw ex;
	}

	// Let subclasses do whatever initialization they like.
	initServletBean();

	if (logger.isDebugEnabled()) {
		logger.debug("Servlet '" + getServletName() + "' configured successfully");
	}
}

Line 21 allows subclasses to add their own initialization routine, which runs after HttpServletBean’s initialization occurred.

In FrameworkServlet.java, we find the following method:

/**
* Overridden method of {@link HttpServletBean}, invoked after any bean properties
 * have been set. Creates this servlet's WebApplicationContext.
 */
@Override
protected final void initServletBean() throws ServletException {
	getServletContext().log("Initializing Spring FrameworkServlet '" + getServletName() + "'");
	if (this.logger.isInfoEnabled()) {
		this.logger.info("FrameworkServlet '" + getServletName() + "': initialization started");
	}
	long startTime = System.currentTimeMillis();

	try {
		this.webApplicationContext = initWebApplicationContext();
		initFrameworkServlet();
	}
	catch (ServletException ex) {
		this.logger.error("Context initialization failed", ex);
		throw ex;
	}
	catch (RuntimeException ex) {
		this.logger.error("Context initialization failed", ex);
		throw ex;
	}
	if (this.logger.isInfoEnabled()) {
		long elapsedTime = System.currentTimeMillis() - startTime;
		this.logger.info("FrameworkServlet '" + getServletName() + "': initialization completed in " +
				elapsedTime + " ms");
	}
}

Note that the method is now final. This means that any classes extending the FrameworkServlet can not change it, so the DispatcherServlet or your own custom servlets inheriting from the FrameworkServlet, can not change the way this initialization happens.
The bulk of the work happens in lines 14-15.
In line 14, The FrameworkServlet initializes the WebApplicationContext – which is Spring’s ApplicationContext (that is – this is the part that hooks the DispatcherServlet instance with Spring) – and then lets the subclass initialize itself in line 15.

Let’s see what happens when the servlet container hooks the servlet up with Spring (with the call to initWebApplicationContext()).

protected WebApplicationContext initWebApplicationContext() {
	WebApplicationContext rootContext =
			WebApplicationContextUtils.getWebApplicationContext(getServletContext());
	WebApplicationContext wac = null;

	if (this.webApplicationContext != null) {
		// A context instance was injected at construction time -> use it
		wac = this.webApplicationContext;
		if (wac instanceof ConfigurableWebApplicationContext) {
			ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
			if (!cwac.isActive()) {
				// The context has not yet been refreshed -> provide services such as
				// setting the parent context, setting the application context id, etc
				if (cwac.getParent() == null) {
					// The context instance was injected without an explicit parent -> set
					// the root application context (if any; may be null) as the parent
					cwac.setParent(rootContext);
				}
				configureAndRefreshWebApplicationContext(cwac);
			}
		}
	}
	if (wac == null) {
		// No context instance was injected at construction time -> see if one
		// has been registered in the servlet context. If one exists, it is assumed
		// that the parent context (if any) has already been set and that the
		// user has performed any initialization such as setting the context id
		wac = findWebApplicationContext();
	}
	if (wac == null) {
		// No context instance is defined for this servlet -> create a local one
		wac = createWebApplicationContext(rootContext);
	}

	if (!this.refreshEventReceived) {
		// Either the context is not a ConfigurableApplicationContext with refresh
		// support or the context injected at construction time had already been
		// refreshed -> trigger initial onRefresh manually here.
		onRefresh(wac);
	}

	if (this.publishContext) {
		// Publish the context as a servlet context attribute.
		String attrName = getServletContextAttributeName();
		getServletContext().setAttribute(attrName, wac);
		if (this.logger.isDebugEnabled()) {
			this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() +
					"' as ServletContext attribute with name [" + attrName + "]");
		}
	}

	return wac;
}

It is a lot of code, but at the end there’s only one important result – this code finds or creates a WebApplicationContext (remember – this is the party responsible for hooking your servlet up with the Spring Container) – and in essence, this gets the ball rolling.
Note that each DispatcherServlet has its own WebApplicationContext, and it is possible to override bean definitions with them (this is probably material for a different post, though).
After this method completes, the DispatcherServlet gets to initialize itself with the initFrameworkServlet() method (see line 15 in the previous code listing). FrameworkServlet leaves this method empty, and expects subclasses to override it. Note, however, that DispatcherServlet does not override the method – all it needs is the WebApplicationContext – which gets populated by FrameworkServlet.

How does the DispatcherServlet actually work?

Ok, I admit – that was a very long-winded explanation of how all this fits together. But the up-side is you don’t absolutely have to know it to work with Spring. In fact, you probably don’t need to know anything apart from configuring your DispatcherServlet in web.xml.

However, you still need to supply some configuration to make the DispatcherServlet work for you. This configuration is found in the servlet-context.xml file that you configured in web.xml (See previous post for a discussion of this file).

When you have all the configuration and wiring of Spring container to the DispatcherServlet sorted – it is time to deploy the application. Once your application is deployed, the web container is open to serve your users’ requests.
As you recall, the mapping in web.xml configures an instance of DispatcherServlet to listen for requests on the ‘/’ context. (Remember – it is absolutely ok to configure multiple instances of the DispatcherServlet in one web.xml file, and each of them will have its own instance of the WebApplicationContext).

When a request comes in, the DispatcherServlet receives it, and finds the right controller (or other handler, but let’s focus on controllers) to hand the request to. This is done in the doService() method.

(The following code is in org.springframework.web.servlet.DispatcherServlet.java)

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
	if (logger.isDebugEnabled()) {
		String requestUri = urlPathHelper.getRequestUri(request);
		logger.debug("DispatcherServlet with name '" + getServletName() + "' processing " + request.getMethod() +
				" request for [" + requestUri + "]");
	}

	// Keep a snapshot of the request attributes in case of an include,
	// to be able to restore the original attributes after the include.
	Map attributesSnapshot = null;
	if (WebUtils.isIncludeRequest(request)) {
		logger.debug("Taking snapshot of request attributes before include");
		attributesSnapshot = new HashMap();
		Enumeration attrNames = request.getAttributeNames();
		while (attrNames.hasMoreElements()) {
			String attrName = (String) attrNames.nextElement();
			if (this.cleanupAfterInclude || attrName.startsWith("org.springframework.web.servlet")) {
				attributesSnapshot.put(attrName, request.getAttribute(attrName));
			}
		}
	}

	this.flashMapManager.requestStarted(request);

	// Make framework objects available to handlers and view objects.
	request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
	request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
	request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
	request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());

	try {
		doDispatch(request, response);
	}
	finally {
		this.flashMapManager.requestCompleted(request);

		// Restore the original attribute snapshot, in case of an include.
		if (attributesSnapshot != null) {
			restoreAttributesAfterInclude(request, attributesSnapshot);
		}
	}
}

doService() is an abstract method on FrameworkServlet – meaning that the non-abstract DispatcherServlet has to overrride it. This is what it does:

  1. Tests whether the request is an include request (line 11). An include request happens when the DispatcherServlet is activated not as a direct result of the user’s original URL request. For example, let’s say that we have a web application that lets users view customers and their orders.
    The code that deals with the original request is building the response back to the user, and needs to display the customer details, but delegates the order-details part of the screen to a different servlet (because you may also view just the order details, and we don’t want to write the code to do that twice).
    Therefore, the response is made up of the customer details and includes a snippet (or multiple snippets) containing order details and served by our DispatcherServlet.
    In this case, the code in lines 13-20 saves the current attributes of the original request, so that they can be restored after we finish dealing with them. Otherwise, we may lose context that’s important to the original request (the customer details URL).
  2. Lines 25-29 add some details to the request. Namely – these are the DispatcherServlet‘s handlers – the objects that will help it serve the request. This is why the code saves the attributes for an included request – otherwise, the original context (i.e. the original request’s WebApplicationContext, LocaleResolver etc) – will be lost forever.
  3. In line 32, the code calls doDispatch(). This method processes the actual dispatching – getting the right object to handle the request.

doDispatch()

This is the meat of the DispatcherServlet code.

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
	HttpServletRequest processedRequest = request;
	HandlerExecutionChain mappedHandler = null;
	int interceptorIndex = -1;

	try {
		ModelAndView mv;
		boolean errorView = false;

		try {
			processedRequest = checkMultipart(request);

			// Determine handler for the current request.
			mappedHandler = getHandler(processedRequest, false);
			if (mappedHandler == null || mappedHandler.getHandler() == null) {
				noHandlerFound(processedRequest, response);
				return;
			}

			// Determine handler adapter for the current request.
			HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

                       // Process last-modified header, if supported by the handler.
			String method = request.getMethod();
			boolean isGet = "GET".equals(method);
			if (isGet || "HEAD".equals(method)) {
				long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
				if (logger.isDebugEnabled()) {
					String requestUri = urlPathHelper.getRequestUri(request);
					logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);
				}
				if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
					return;
				}
			}

			// Apply preHandle methods of registered interceptors.
			HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();
			if (interceptors != null) {
				for (int i = 0; i < interceptors.length; i++) { 					HandlerInterceptor interceptor = interceptors[i]; 					if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) { 						triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null); 						return; 					} 					interceptorIndex = i; 				} 			} 			// Actually invoke the handler. 			mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); 			// Do we need view name translation? 			if (mv != null && !mv.hasView()) { 				mv.setViewName(getDefaultViewName(request)); 			} 			// Apply postHandle methods of registered interceptors. 			if (interceptors != null) { 				for (int i = interceptors.length - 1; i >= 0; i--) {
					HandlerInterceptor interceptor = interceptors[i];
					interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv);
				}
			}
		}
		catch (ModelAndViewDefiningException ex) {
			logger.debug("ModelAndViewDefiningException encountered", ex);
			mv = ex.getModelAndView();
		}
		catch (Exception ex) {
			Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
			mv = processHandlerException(processedRequest, response, handler, ex);
			errorView = (mv != null);
		}

		// Did the handler return a view to render?
		if (mv != null && !mv.wasCleared()) {
			render(mv, processedRequest, response);
			if (errorView) {
				WebUtils.clearErrorRequestAttributes(request);
			}
		}
		else {
			if (logger.isDebugEnabled()) {
				logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
						"': assuming HandlerAdapter completed request handling");
			}
		}

		// Trigger after-completion for successful outcome.
		triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
	}

	catch (Exception ex) {
		// Trigger after-completion for thrown exception.
		triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
		throw ex;
	}
	catch (Error err) {
		ServletException ex = new NestedServletException("Handler processing failed", err);
		// Trigger after-completion for thrown exception.
		triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
		throw ex;
	}

	finally {
		// Clean up any resources used by a multipart request.
		if (processedRequest != request) {
			cleanupMultipart(processedRequest);
		}
	}
}
  1. Line 14: call getHandler() to find a handler (or handler chain) for the request.
    In a sense, the DispatcherServlet is a means of mapping incoming requests to handlers of these requests. To do this, it contains an org.springframework.web.servle.HandlerMapping instance.
    The HandlerMapping is quite a cool feature of Spring. It is an interface that has one method:
    HandlerExecutionChain getHandler(HttpServletRequest request)

    . Implementations of this interface receive a request object, analyse it, and return a chain of handlers that will handle the request.
    When the code to initialize DispatcherServlet as FrameworkServlet runs, it initialises the HandlerMapping, from – you guessed it – the ApplicationContext!! so you see – this is how it all works. The initWebApplicationContext() method attaches a WebApplicationContext to the DispatcherServlet. Then, when the DispatcherServlet initialises, it builds its mapping of requests to handlers, and then – when a request comes in – it uses this map to look up the right chain of handlers.

  2. In line 21, assuming a correct handler was found, the code finds the HandlerAdapter for the request. The getHandler() method always returns a chain of handlers. If there’s only one handler defined for the request – it still get wrapped in a chain. The getHandlerAdapter() method returns an adapter that the DispatcherServlet can use to deal with the request. (It is only called to handle the request in line 51, though, as there’s the small matter of interceptors that to deal with first).
  3. Lines 24-35 deal with HTTP’s last-modified header – and it’s irrelevant for this discussion I think.
  4. Lines 38-48 iterate over the interceptors configured for the handler.
    An org.springframework.web.servlet.HandlerInterceptor is, in a way, Spring’s version of a javax.servlet.Filter. This is only true in the sense that both HandlerInterceptor and Filter can be chained around request (or response, or resource), and the container then calls their relevant methods before and/or after dealing with the actual request. They differ in other respects. A Filter is normally used for “coarse” actions on the objects it wraps: logging, authentication/authorisation, compression, etc. On the other hand, a HandlerInterceptor will normally be used to extract pieces of code that may be relevant for all HandlerAdapters, and since they receive a handle to the Handler object itself – they can use its attributes and callbacks. In this sense, HandlerInterceptors are more powerful than Filters.
    The code in these lines calls the preHandle() method on each Interceptor in the interceptor chain. If the call returns false – the chain of execution stops, and the doDispatch() method returns. Again, in contrast with a Filter – the HandlerInterceptor invocation is a bit more graceful, and perhaps a bit less error prone. When a Filter.doFilter() method executes, it needs to include a call to the next Filter in the filter chain – or the request hangs. It is easy to forget to code that call, which leads to silly bugs. With a HandlerInterceptor – because the method signature enforces returning a value – this type of errors is less common.
  5. Line 51 transfers the request and response objects to the HandlerAdapter itself – and finally the request itself gets processed. Note that the return value from the handle method is a ModelAndView object (again, see here) – this is to be expected in an MVC framework.
  6. Lines 54-56 – After the HandlerAdapter finished its work – control returns to the DispatcherServlet. This time it is to make sure that a view name is found and rendered back to the user. Therefore, if the ModelAndView object returned from handle() does not in fact contain a view – it will receive the default view name for the request.
    Important: note that if no ,ModelAndView object is returned – there will be no attempt at creating one and returning a view. This is normally to allow the application “a way out” in case there’s some security or availability issue. In these cases – the framework will deal with the situation by rendering an error view. Additionally, this is very useful for handling Ajax requests, when you don’t want the application to render a new view.
  7. Lines 59-64 repeat the HandlerInterceptor chain process, but this time it calls the postHandle() methods on the interceptors. It is important to note that any intervention with the process needs to have happened on the preHandle() chain in lines 38-48. When the request passes through postHandle() – it can’t be stopped in a normal flow (though the preHandle() method signature allows you to throw an Exception, which will be caught outside the loop).

That’s it…

Well, that was a long post, wasn’t it. Good on you for reading up to here. I will try and post some more in the next few weeks.

11 thoughts on “Spring MVC – DispatcherServlet

  1. dominicus

    “You’ll be fine as long as you remember the three simple rules:”

    third rule?

  2. clay

    Nice walk-through. Just one correction:

    It is a container that has one method

    Should read:

    It is an interface that has one method

  3. Guddu

    In Spring web.xml there is various servlet tag and inside that tag there is various dispatcherservlet. Is every dispatcher servlet create its own spring container ie. webapplicationcontext?

  4. uwspstar

    step by step to explain how the DispatcherServlet works. It is really good start point for me to understand Spring MVC. Thanks for this post!

  5. Zhu

    Very good illumination of spring DispatcherServlet!
    The doDispatch() code snippet is not complete, call of handle’s interceptors’ preHandle() is missing.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>