Close

Spring MVC - Understanding HandlerAdapter

[Last Updated: Sep 26, 2026]

The interface HandlerAdapter is responsible for invoking a handler method and returning the response as ModelAndView to the DispatcherServlet.

Definition of HandlerAdapter

Version: 7.0.6
 package org.springframework.web.servlet;
 public interface HandlerAdapter {
     boolean supports(Object handler); 1
     ModelAndView handle(HttpServletRequest request, 2
                         HttpServletResponse response,
                         Object handler)
                         throws Exception;
 }
1Given a handler instance, return whether this HandlerAdapter can support it.
2Use the given handler to handle this request.

HandlerAdapter vs HandlerMapping

DispatcherServlet uses HandlerMapping to find the right handler (a controller method or object) for a request. Once a handler is found, DispatcherServlet uses HandlerAdapter to actually invoke that handler.

You can register more than one HandlerAdapter. This is what makes DispatcherServlet extensible: how a handler is selected (HandlerMapping's job) and how it is invoked (HandlerAdapter's job) can each be customized independently of the other.

A HandlerMapping is not tied to any specific HandlerAdapter. Even so, the type of handler object a HandlerMapping returns — the object you get from HandlerExecutionChain#getHandler() — is exactly what a HandlerAdapter looks at to decide whether it can handle the request.

For each registered HandlerAdapter, DispatcherServlet first calls supports(handler).

  • If it returns true, DispatcherServlet calls that adapter's handle(request, response, handler) method with the same handler object, and the adapter invokes it.
  • If it returns false, DispatcherServlet moves on and tries the next registered HandlerAdapter.
  • If none of the registered HandlerAdapters support the handler, DispatcherServlet throws an exception.

Default HandlerAdapters

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

Note: As of Spring Framework 6 (and continuing in 7.x), WebMvcConfigurationSupport (and therefore @EnableWebMvc) and DispatcherServlet.properties both register a fourth default HandlerAdapter, HandlerFunctionAdapter, which handles functional endpoints defined via RouterFunction beans (the functional web framework). The example below is pinned to an older Spring version and therefore only prints the three "traditional" adapters described in this tutorial.

Let's print the list of HandlerAdapters during runtime:

@Controller
public class TestController {

    @Autowired
    ApplicationContext context;

    @RequestMapping(value = "/test")
    @ResponseBody
    public String handleRequest() {
        BeanFactoryUtils
                .beansOfTypeIncludingAncestors(context,
                                               HandlerAdapter.class,
                                               true,
                                               false)
                .entrySet()
                .stream()
                .sorted(Map.Entry.comparingByKey())
                .forEach(e ->
                                 System.out.printf("%s=%s%n",
                                                   e.getKey(),
                                                   e.getValue().getClass()
                                                    .getSimpleName()));
        return "response from /test";
    }
}

To try examples, run embedded Jetty (configured in pom.xml of example project below):

mvn jetty:run

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

$ curl -s "http://localhost:8080/test"
response from /test

Server Output


handlerFunctionAdapter=HandlerFunctionAdapter
httpRequestHandlerAdapter=HttpRequestHandlerAdapter
requestMappingHandlerAdapter=RequestMappingHandlerAdapter
simpleControllerHandlerAdapter=SimpleControllerHandlerAdapter

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

  • HandlerFunctionAdapter (since 5.2):

    HandlerAdapter implementation that supports HandlerFunctions. A HandlerFunction represents a function that handles a request.

  • RequestMappingHandlerAdapter:

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

  • HttpRequestHandlerAdapter:

    It supports handler objects of type HttpRequestHandler.

  • SimpleControllerHandlerAdapter:

    It supports handler objects of type Controller.

RequestMappingHandlerAdapter is used by DispatcherServlet when we use @RequestMapping. We have been using only this strategy in our tutorials so far. In the 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 7.0.6 (Spring Web MVC)
     Version Compatibility: 3.2.9.RELEASE - 7.0.6Version List
    ×

    Version compatibilities of spring-webmvc with this example:

      javax.servlet-api:3.x
    • 3.2.9.RELEASE
    • 3.2.10.RELEASE
    • 3.2.11.RELEASE
    • 3.2.12.RELEASE
    • 3.2.13.RELEASE
    • 3.2.14.RELEASE
    • 3.2.15.RELEASE
    • 3.2.16.RELEASE
    • 3.2.17.RELEASE
    • 3.2.18.RELEASE
    • 4.0.0.RELEASE
    • 4.0.1.RELEASE
    • 4.0.2.RELEASE
    • 4.0.3.RELEASE
    • 4.0.4.RELEASE
    • 4.0.5.RELEASE
    • 4.0.6.RELEASE
    • 4.0.7.RELEASE
    • 4.0.8.RELEASE
    • 4.0.9.RELEASE
    • 4.1.0.RELEASE
    • 4.1.1.RELEASE
    • 4.1.2.RELEASE
    • 4.1.3.RELEASE
    • 4.1.4.RELEASE
    • 4.1.5.RELEASE
    • 4.1.6.RELEASE
    • 4.1.7.RELEASE
    • 4.1.8.RELEASE
    • 4.1.9.RELEASE
    • 4.2.0.RELEASE
    • 4.2.1.RELEASE
    • 4.2.2.RELEASE
    • 4.2.3.RELEASE
    • 4.2.4.RELEASE
    • 4.2.5.RELEASE
    • 4.2.6.RELEASE
    • 4.2.7.RELEASE
    • 4.2.8.RELEASE
    • 4.2.9.RELEASE
    • 4.3.0.RELEASE
    • 4.3.1.RELEASE
    • 4.3.2.RELEASE
    • 4.3.3.RELEASE
    • 4.3.4.RELEASE
    • 4.3.5.RELEASE
    • 4.3.6.RELEASE
    • 4.3.7.RELEASE
    • 4.3.8.RELEASE
    • 4.3.9.RELEASE
    • 4.3.10.RELEASE
    • 4.3.11.RELEASE
    • 4.3.12.RELEASE
    • 4.3.13.RELEASE
    • 4.3.14.RELEASE
    • 4.3.15.RELEASE
    • 4.3.16.RELEASE
    • 4.3.17.RELEASE
    • 4.3.18.RELEASE
    • 4.3.19.RELEASE
    • 4.3.20.RELEASE
    • 4.3.21.RELEASE
    • 4.3.22.RELEASE
    • 4.3.23.RELEASE
    • 4.3.24.RELEASE
    • 4.3.25.RELEASE
    • 4.3.26.RELEASE
    • 4.3.27.RELEASE
    • 4.3.28.RELEASE
    • 4.3.29.RELEASE
    • 4.3.30.RELEASE
    • 5.0.0.RELEASE
    • 5.0.1.RELEASE
    • 5.0.2.RELEASE
    • 5.0.3.RELEASE
    • 5.0.4.RELEASE
    • 5.0.5.RELEASE
    • 5.0.6.RELEASE
    • 5.0.7.RELEASE
    • 5.0.8.RELEASE
    • 5.0.9.RELEASE
    • 5.0.10.RELEASE
    • 5.0.11.RELEASE
    • 5.0.12.RELEASE
    • 5.0.13.RELEASE
    • 5.0.14.RELEASE
    • 5.0.15.RELEASE
    • 5.0.16.RELEASE
    • 5.0.17.RELEASE
    • 5.0.18.RELEASE
    • 5.0.19.RELEASE
    • 5.0.20.RELEASE
    • 5.1.0.RELEASE
    • 5.1.1.RELEASE
    • 5.1.2.RELEASE
    • 5.1.3.RELEASE
    • 5.1.4.RELEASE
    • 5.1.5.RELEASE
    • 5.1.6.RELEASE
    • 5.1.7.RELEASE
    • 5.1.8.RELEASE
    • 5.1.9.RELEASE
    • 5.1.10.RELEASE
    • 5.1.11.RELEASE
    • 5.1.12.RELEASE
    • 5.1.13.RELEASE
    • 5.1.14.RELEASE
    • 5.1.15.RELEASE
    • 5.1.16.RELEASE
    • 5.1.17.RELEASE
    • 5.1.18.RELEASE
    • 5.1.19.RELEASE
    • 5.1.20.RELEASE
    • 5.2.0.RELEASE
    • 5.2.1.RELEASE
    • 5.2.2.RELEASE
    • 5.2.3.RELEASE
    • 5.2.4.RELEASE
    • 5.2.5.RELEASE
    • 5.2.6.RELEASE
    • 5.2.7.RELEASE
    • 5.2.8.RELEASE
    • 5.2.9.RELEASE
    • 5.2.10.RELEASE
    • 5.2.11.RELEASE
    • 5.2.12.RELEASE
    • 5.2.13.RELEASE
    • 5.2.14.RELEASE
    • 5.2.15.RELEASE
    • 5.2.16.RELEASE
    • 5.2.17.RELEASE
    • 5.2.18.RELEASE
    • 5.2.19.RELEASE
    • 5.2.20.RELEASE
    • 5.2.21.RELEASE
    • 5.2.22.RELEASE
    • 5.2.23.RELEASE
    • 5.2.24.RELEASE
    • 5.2.25.RELEASE
    • 5.3.0
    • 5.3.1
    • 5.3.2
    • 5.3.3
    • 5.3.4
    • javax.servlet-api:4.x
    • 5.3.5
    • 5.3.6
    • 5.3.7
    • 5.3.8
    • 5.3.9
    • 5.3.10
    • 5.3.11
    • 5.3.12
    • 5.3.13
    • 5.3.14
    • 5.3.15
    • 5.3.16
    • 5.3.17
    • 5.3.18
    • 5.3.19
    • 5.3.20
    • 5.3.21
    • 5.3.22
    • 5.3.23
    • 5.3.24
    • 5.3.25
    • 5.3.26
    • 5.3.27
    • 5.3.28
    • 5.3.29
    • 5.3.30
    • 5.3.31
    • 5.3.32
    • 5.3.33
    • 5.3.34
    • 5.3.35
    • 5.3.36
    • 5.3.37
    • 5.3.38
    • 5.3.39
    • javax.* -> jakarta.*
      jakarta.servlet-api:6.x
      Java 17 min
    • 6.0.0
    • 6.0.1
    • 6.0.2
    • 6.0.3
    • 6.0.4
    • 6.0.5
    • 6.0.6
    • 6.0.7
    • 6.0.8
    • 6.0.9
    • 6.0.10
    • 6.0.11
    • 6.0.12
    • 6.0.13
    • 6.0.14
    • 6.0.15
    • 6.0.16
    • 6.0.17
    • 6.0.18
    • 6.0.19
    • 6.0.20
    • 6.0.21
    • 6.0.22
    • 6.0.23
    • 6.1.0
    • 6.1.1
    • 6.1.2
    • 6.1.3
    • 6.1.4
    • 6.1.5
    • 6.1.6
    • 6.1.7
    • 6.1.8
    • 6.1.9
    • 6.1.10
    • 6.1.11
    • 6.1.12
    • 6.1.13
    • 6.1.14
    • 6.1.15
    • 6.1.16
    • 6.1.17
    • 6.1.18
    • 6.1.19
    • 6.1.20
    • 6.1.21
    • 6.2.0
    • 6.2.1
    • 6.2.2
    • 6.2.3
    • 6.2.4
    • 6.2.5
    • 6.2.6
    • 6.2.7
    • 6.2.8
    • 6.2.9
    • 6.2.10
    • 6.2.11
    • 6.2.12
    • 6.2.13
    • 6.2.14
    • 6.2.15
    • 6.2.16
    • 6.2.17
    • 6.2.18
    • 6.2.19
    • 7.0.0
    • 7.0.1
    • 7.0.2
    • 7.0.3
    • 7.0.4
    • 7.0.5
    • 7.0.6

    Versions in green have been tested.

  • jakarta.servlet-api 6.1.0 (Jakarta Servlet API documentation)
  • JDK 25
  • Maven 3.9.11

Spirng MVC - HandlerAdapter List Select All Download
  • spring-default-handler-adapters
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • TestController.java

    See Also

    Join