Spring MVC HandlerAdapter 详解:处理器适配器的原理与实战
HandlerAdapter(处理器适配器)是 Spring MVC 中连接 DispatcherServlet 与 Handler(处理器,如 Controller) 的关键组件。由于 Spring MVC 支持多种 Handler 实现方式(如实现 Controller 接口、HttpRequestHandler 接口、注解驱动的 @Controller 方法),DispatcherServlet 无法直接调用不同类型的 Handler,需通过 HandlerAdapter 进行 “适配”——将统一的调用逻辑转换为具体 Handler 的执行方式,彻底解耦前端控制器与处理器。从 “核心定义→适配器模式→实现类解析→核心流程源码” 四个维度,彻底讲透 HandlerAdapter 的工作机制。
HandlerAdapter 核心定义与设计思想
1. 核心接口与方法
HandlerAdapter 接口定义了所有适配器的通用行为,共 3 个核心方法,覆盖 “适配判断→执行逻辑→资源时间戳” 三大功能:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public interface HandlerAdapter {
boolean supports(Object handler);
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
long getLastModified(HttpServletRequest request, Object handler); }
|
2. 设计思想:适配器模式
HandlerAdapter 是 适配器模式 的典型应用,核心目标是 “将不同类型的 Handler 统一适配为 DispatcherServlet 可调用的接口”。
- 问题场景:DispatcherServlet 只知道调用
HandlerAdapter.handle() 方法,但 Handler 有多种实现(如 Controller、HttpRequestHandler、HandlerMethod),执行方式各不相同(如 handleRequest()、service()、反射调用注解方法);
- 解决方案:每种 Handler 对应一个 HandlerAdapter,适配器内部封装具体的执行逻辑,DispatcherServlet 只需通过适配器调用,无需关心 Handler 类型;
- 扩展优势:新增 Handler 类型时,只需添加对应的 HandlerAdapter,无需修改 DispatcherServlet 代码(符合开闭原则)。
常用 HandlerAdapter 实现类解析
Spring MVC 提供了多个 HandlerAdapter 实现,分别适配不同类型的 Handler,覆盖从传统接口到现代注解的所有场景。以下是核心实现类的对比与源码解析:
| 实现类 |
适配的 Handler 类型 |
核心执行逻辑 |
适用场景 |
优缺点 |
HttpRequestHandlerAdapter |
实现 HttpRequestHandler 接口的类 |
调用 handler.handleRequest(request, response),无返回值(Handler 自行处理响应) |
无需视图渲染的场景(如返回 JSON、文件下载) |
轻量灵活,无视图依赖;需手动处理响应流 |
SimpleControllerHandlerAdapter |
实现 Controller 接口的类 |
调用 handler.handleRequest(request, response),返回 ModelAndView |
传统视图驱动项目(如 JSP 页面渲染) |
支持视图渲染;接口耦合度高,灵活性低 |
SimpleServletHandlerAdapter |
实现 Servlet 接口的类 |
调用 handler.service(request, response),无返回值 |
兼容 legacy Servlet 组件 |
复用 Servlet 代码;重量级,不符合 MVC 分层 |
RequestMappingHandlerAdapter |
封装注解方法的 HandlerMethod(@Controller + @RequestMapping) |
反射调用注解方法,支持参数绑定、返回值处理(如 @ResponseBody) |
现代注解驱动项目(主流) |
支持复杂参数 / 返回值,灵活性高;逻辑复杂 |
1. 基础适配器:HttpRequestHandlerAdapter
适配实现 HttpRequestHandler 接口的 Handler,核心是 “Handler 自行处理请求响应”,无需返回 ModelAndView(适合无视图场景)。
源码解析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| public class HttpRequestHandlerAdapter implements HandlerAdapter {
@Override public boolean supports(Object handler) { return (handler instanceof HttpRequestHandler); }
@Override public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { ((HttpRequestHandler) handler).handleRequest(request, response); return null; }
@Override public long getLastModified(HttpServletRequest request, Object handler) { if (handler instanceof LastModified) { return ((LastModified) handler).getLastModified(request); } return -1L; } }
|
实战示例
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Component("/download") public class FileDownloadHandler implements HttpRequestHandler { @Override public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws IOException { response.setContentType("application/octet-stream"); response.setHeader("Content-Disposition", "attachment;filename=test.txt"); try (OutputStream os = response.getOutputStream()) { os.write("Hello, HttpRequestHandler".getBytes(StandardCharsets.UTF_8)); } } }
|
- 访问
/download 时,HttpRequestHandlerAdapter 会调用 handleRequest 方法,直接向响应流写入文件内容,无需视图渲染。
2. 传统视图适配器:SimpleControllerHandlerAdapter
适配实现 Controller 接口的 Handler,核心是 “返回 ModelAndView 用于视图渲染”,适合传统 JSP 项目。
源码解析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public class SimpleControllerHandlerAdapter implements HandlerAdapter {
@Override public boolean supports(Object handler) { return (handler instanceof Controller); }
@Override public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return ((Controller) handler).handleRequest(request, response); }
@Override public long getLastModified(HttpServletRequest request, Object handler) { if (handler instanceof LastModified) { return ((LastModified) handler).getLastModified(request); } return -1L; } }
|
实战示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class UserController implements Controller { @Override public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) { List<String> userList = Arrays.asList("张三", "李四"); ModelAndView mav = new ModelAndView("userList"); mav.addObject("userList", userList); return mav; } }
<bean name="/user/list" class="com.example.controller.UserController"/>
|
- 访问
/user/list 时,SimpleControllerHandlerAdapter 调用 handleRequest 方法,返回的 ModelAndView 会被视图解析器渲染为 JSP 页面。
3. 兼容适配器:SimpleServletHandlerAdapter
适配实现 Servlet 接口的 Handler,核心是 “复用 legacy Servlet 代码”,适合逐步迁移旧项目时使用。
源码解析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public class SimpleServletHandlerAdapter implements HandlerAdapter {
@Override public boolean supports(Object handler) { return (handler instanceof Servlet); }
@Override public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { ((Servlet) handler).service(request, response); return null; }
@Override public long getLastModified(HttpServletRequest request, Object handler) { return -1; } }
|
注意事项
- 该适配器仅用于兼容旧 Servlet 组件,不推荐在纯 Spring MVC 项目中使用(破坏 MVC 分层,Servlet 直接处理请求响应)。
4. 现代核心适配器:RequestMappingHandlerAdapter
RequestMappingHandlerAdapter 是 Spring MVC 3.1+ 引入的核心适配器,专门适配 HandlerMethod(封装 @Controller 类中的 @RequestMapping 方法),支持参数绑定(如 @RequestParam、@RequestBody)、返回值处理(如 @ResponseBody)、数据校验(如 @Valid)等现代特性,是当前注解驱动项目的默认适配器。
(1)初始化流程:准备核心组件
RequestMappingHandlerAdapter 实现 InitializingBean 接口,在 Spring 容器初始化时调用 afterPropertiesSet 方法,初始化参数解析器、返回值处理器等核心组件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| @Override public void afterPropertiesSet() { initControllerAdviceCache();
if (this.argumentResolvers == null) { List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers(); this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers); }
if (this.initBinderArgumentResolvers == null) { List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers(); this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers); }
if (this.returnValueHandlers == null) { List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers(); this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers); } }
|
核心组件说明:
HandlerMethodArgumentResolver:参数解析器,负责将 HTTP 请求参数(如 URL 参数、请求体 JSON)绑定到 HandlerMethod 的方法参数(如 @RequestParam String name、@RequestBody User user);
HandlerMethodReturnValueHandler:返回值处理器,负责将 HandlerMethod 的返回值(如 User 对象、String 视图名)转换为响应(如 JSON 字符串、ModelAndView);
@ControllerAdvice 缓存:存储全局增强逻辑(如全局异常处理、全局数据绑定),供参数解析器 / 返回值处理器使用。
(2)请求处理流程:执行 HandlerMethod
RequestMappingHandlerAdapter 的核心逻辑在 handleInternal 方法中,最终通过 invokeHandlerMethod 反射调用注解方法,完成参数绑定、方法执行、返回值处理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| @Override protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ModelAndView mav; checkRequest(request);
if (this.synchronizeOnSession) { HttpSession session = request.getSession(false); if (session != null) { Object mutex = WebUtils.getSessionMutex(session); synchronized (mutex) { mav = invokeHandlerMethod(request, response, handlerMethod); } } else { mav = invokeHandlerMethod(request, response, handlerMethod); } } else { mav = invokeHandlerMethod(request, response, handlerMethod); }
if (!response.containsHeader(HEADER_CACHE_CONTROL)) { if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) { applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers); } else { prepareResponse(response); } }
return mav; }
|
关键方法 invokeHandlerMethod:反射调用注解方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ServletWebRequest webRequest = new ServletWebRequest(request, response); try { WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod); invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers); invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers); invocableMethod.setDataBinderFactory(binderFactory); invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
ModelAndViewContainer mavContainer = new ModelAndViewContainer(); mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request)); modelFactory.initModel(webRequest, mavContainer, invocableMethod); mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); asyncManager.registerCallableInterceptors(this.callableInterceptors); asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);
invocableMethod.invokeAndHandle(webRequest, mavContainer);
if (asyncManager.isConcurrentHandlingStarted()) { return null; }
return getModelAndView(mavContainer, modelFactory, webRequest); } finally { webRequest.requestCompleted(); } }
|
核心步骤拆解:
- 参数绑定:
argumentResolvers 根据方法参数注解(如 @RequestParam),从请求中提取参数并转换为 Java 类型(如 String→Integer);
- 方法执行:通过反射调用
@RequestMapping 标注的方法,执行业务逻辑;
- 返回值处理:
returnValueHandlers 根据返回值类型(如 User 对象、String 视图名)或注解(如 @ResponseBody),生成响应(如 JSON 字符串、ModelAndView);
- Model 处理:更新 Model 数据(如同步
@SessionAttributes 数据到 Session),构建最终的 ModelAndView(若有视图则渲染,无则返回 null)。
HandlerAdapter 的配置与生效机制
1. 自动配置:mvc:annotation-driven(推荐)
Spring MVC 3.1+ 提供 mvc:annotation-driven 标签,自动注册 RequestMappingHandlerAdapter(以及 RequestMappingHandlerMapping、ExceptionHandlerExceptionResolver),无需手动配置:
1 2
| <mvc:annotation-driven/>
|
- 该配置会自动初始化
RequestMappingHandlerAdapter 所需的参数解析器、返回值处理器,支持 @RequestBody、@ResponseBody、@Valid 等注解。
2. 手动配置(适用于特殊场景)
若需自定义适配器(如扩展参数解析器),可手动在 XML 或 Java 配置中声明:
示例:手动配置 RequestMappingHandlerAdapter 并扩展参数解析器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| @Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer {
@Bean public CurrentUserArgumentResolver currentUserArgumentResolver() { return new CurrentUserArgumentResolver(); }
@Bean public RequestMappingHandlerAdapter requestMappingHandlerAdapter() { RequestMappingHandlerAdapter adapter = new RequestMappingHandlerAdapter(); List<HandlerMethodArgumentResolver> resolvers = adapter.getDefaultArgumentResolvers(); List<HandlerMethodArgumentResolver> customResolvers = new ArrayList<>(); customResolvers.add(currentUserArgumentResolver()); customResolvers.addAll(resolvers); adapter.setArgumentResolvers(customResolvers); return adapter; } }
|
3. 适配优先级:多个 HandlerAdapter 共存
当容器中存在多个 HandlerAdapter 时,DispatcherServlet 会按以下规则选择:
- 按注册顺序遍历:DispatcherServlet 维护
handlerAdapters 列表,按注册顺序依次检查 supports(handler);
- 第一个匹配的适配器执行:找到第一个返回
true 的适配器,调用其 handle() 方法;
- 优先级控制:通过
Ordered 接口或 order 属性调整优先级(值越小,优先级越高)。
例如:RequestMappingHandlerAdapter 的优先级高于 SimpleControllerHandlerAdapter,确保注解驱动的 Handler 优先被处理。
常见问题与最佳实践
1. 如何自定义参数解析器 / 返回值处理器?
通过 WebMvcConfigurer 的 addArgumentResolvers/addReturnValueHandlers 方法扩展:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer {
@Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { resolvers.add(new CurrentUserArgumentResolver()); }
@Override public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) { handlers.add(new CustomJsonReturnValueHandler()); } }
|
2. 最佳实践建议
- 优先使用
mvc:annotation-driven:自动注册 RequestMappingHandlerAdapter,无需手动配置,支持现代注解特性;
- 避免滥用多个适配器:除非需兼容旧 Handler(如
Controller 接口),否则仅保留 RequestMappingHandlerAdapter,减少适配开销;
- 扩展优先于自定义适配器:新增参数绑定或返回值处理逻辑时,优先扩展
HandlerMethodArgumentResolver/HandlerMethodReturnValueHandler,而非自定义 HandlerAdapter;
- 理解参数解析器顺序:自定义参数解析器需注意优先级(如
@RequestBody 解析器应优先于 @RequestParam 解析器)。
总结
HandlerAdapter 是 Spring MVC 适配器模式的核心体现,通过 “统一接口 + 不同实现” 解耦 DispatcherServlet 与 Handler,支持多种处理器类型的灵活扩展。其中:
- 基础适配器(
HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter)适合传统项目,逻辑简单但灵活性低;
- 核心适配器(
RequestMappingHandlerAdapter)是现代注解驱动项目的基石,支持参数绑定、返回值处理、数据校验等复杂特性,是实际开发的首选
v1.3.10