Close

Spring MVC - Understanding HandlerAdapter

[Last Updated: Dec 7, 2017]

The interface HandlerAdapter is responsible to invoke a handler method and to return the response as ModelAndView to the DispatcherServlet. Here's the interface snippet:

package org.springframework.web.servlet;

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

HandlerAdapter vs HandlerMapping

DispatcherServlet uses the HandlerMappings to select the handler method/object, whereas, HandlerAdapter is used to actually invoke the handler method.

Multiple HandlerAdapters can be registered. This allows DispatcherServlet to be extensible for how to select a request handler (with HandleMapping) and then handle the requests (with HandlerAdapter).

A HandlerMapping instance is not tied/coupled to a particular HandlerAdapter instance, but the type of handler object returned by a HandlerMapping (in HandlerExecutionChain response i.e. the object returned by HandlerExecutionChain#getHandler() , see the last tutorial) is certainly a factor for a particular HandlerAdapter to decide whether to handle the request or not to handle it.

DispatcherServlet calls HandlerAdapter#supports(HandlerExecutionChain#getHandler()) method first, before invoking HandlerAdapter#handle(). If supports() returns true then HandlerAdapter#handle() method is invoked with the last argument passed with the object returned by HandlerExecutionChain#getHandler(). handle() method then invokes it as the final handler method. If HandlerAdapter#supports() method returns false then the current HandlerAdapter is skipped and the next HandlerAdapter is attempted. If no HandlerAdapter, among the registered ones, supports the handler object then an exception is thrown.

Default HandlerAdapters

Since we are using @EnableWebMvc, we can find the list of default HandlerAdapters from WebMvcConfigurationSupport doc. If you are using older configuration approach then you can checkout DispatcherServlet.properties to see the list.

Let's print the list of HandlerAdapters during runtime:

@Controller
public class TestController {
  
  @Autowired
  ApplicationContext context;
  
  @RequestMapping(value = "/test")
  @ResponseBody
  public String handleRequest () {
      Map<String, HandlerAdapter> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
                context, HandlerAdapter.class, true, false);
      
      matchingBeans.forEach((k, v) -> System.out.printf("%s=%s%n",
                                                        k,
                                                        v.getClass().getSimpleName()));
      return "response from /test";
  }
}

Accessing http://localhost:8080/test prints following output on the server console:

requestMappingHandlerAdapter=RequestMappingHandlerAdapter
httpRequestHandlerAdapter=HttpRequestHandlerAdapter
simpleControllerHandlerAdapter=SimpleControllerHandlerAdapter

Let's understand how each one of the above handlers works.

  • RequestMappingHandlerAdapter:

    This HandlerAdapter targets the handler classes/methods annotated with @RequestMapping. The supports() method returns true if the given handler type (returned from HandlerMapping) is HandlerMethod.
    HandlerMethod wraps the information about handler method/parameters/returned-type and it's enclosing @Controller bean.

  • HttpRequestHandlerAdapter:

    It supports the handler objects of type HttpRequestHandler.

  • SimpleControllerHandlerAdapter:

    It supports the handler objects of type Controller.

RequestMappingHandlerAdapter is used by the DispatcherServlet when we use @RequestMapping. We have been using only this strategy in our tutorials so far. In next tutorials, we will see examples of how to make use of the other two default HandlerAdapters.

Example Project

Dependencies and Technologies Used:

  • spring-webmvc 4.3.9.RELEASE: Spring Web MVC.
  • javax.servlet-api 3.0.1 Java Servlet API
  • JDK 1.8
  • Maven 3.3.9

Spring Handler Adapter Select All Download
  • spring-default-handler-adapters
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • TestController.java

    See Also