The interface HandlerAdapter is responsible for invoking a handler method and returning the response as ModelAndView to the DispatcherServlet.
Definition of HandlerAdapterVersion: 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;
}
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 ProjectDependencies and Technologies Used: - spring-webmvc 7.0.6 (Spring Web MVC)
Version Compatibility: 3.2.9.RELEASE - 7.0.6 Version compatibilities of spring-webmvc with this example: Versions in green have been tested.
- jakarta.servlet-api 6.1.0 (Jakarta Servlet API documentation)
- JDK 25
- Maven 3.9.11
|