biancheng-Spring MVC-HandlerAdapter
二、HandlerAdapter
根据 Handler 来找到支持它的 HandlerAdapter,通过 HandlerAdapter 执行这个 Handler 得到 ModelAndView 对象。HandlerAdapter 接口中的方法如下:
- boolean supports(Object handler); // 当前 HandlerAdapter 是否支持这个 Handler
- ModelAndView handle(HttpServletRequest req, HttpServletResponse res, Object handler); // 利用 Handler 处理请求
- long getLastModified(HttpServletRequest request, Object handler);
1 RequestMappingHandlerAdapter
从上面的文章中可以知道,利用 RequestMappingHandlerMapping 获取的 Handler 是 HadnlerMethod 类型,它代表 Controller 里要执行的方法,而 RequestMappingHandlerAdapter 可以执行 HadnlerMethod 对象。
RequestMappingHandlerAdapter 的 handle() 方法是在它的父类 AbstractHandlerMethodAdapter 类中实现的,源码如下所示
@Override public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return handleInternal(request, response, (HandlerMethod) handler); }
handleInternal() 方法是由 RequestMappingHandlerAdapter 自己来实现的,源码如下所示
@Override protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { // 是否通过 @SessionAttributes 注释声明了 session 属性。 if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) { checkAndPrepare(request, response, this.cacheSecondsForSessionAttributeHandlers, true); } else { checkAndPrepare(request, response, true); } // 是否需要在 synchronize 块中执行 if (this.synchronizeOnSession) { HttpSession session = request.getSession(false); if (session != null) { Object mutex = WebUtils.getSessionMutex(session); synchronized (mutex) { // 执行 HandlerMethod return invokeHandleMethod(request, response, handlerMethod); } } } // 执行 HandlerMethod,得到 ModelAndView return invokeHandleMethod(request, response, handlerMethod); }
继续再来看一下如何得到 ModelAndView,invokeHandlerMethod() 方法如下
private ModelAndView invokeHandleMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { // ServletWebRequest webRequest = new ServletWebRequest(request, response); // 数据绑定 WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod); ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory); // 绑定参数,执行方法 ServletInvocableHandlerMethod requestMappingMethod = createRequestMappingMethod(handlerMethod, binderFactory); // 创建模型和视图容器 ModelAndViewContainer mavContainer = new ModelAndViewContainer(); // 设置FlasgMap中的值 mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request)); // 初始化模型 modelFactory.initModel(webRequest, mavContainer, requestMappingMethod); mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect); AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response); asyncWebRequest.setTimeout(this.asyncRequestTimeout); final WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); asyncManager.setTaskExecutor(this.taskExecutor); asyncManager.setAsyncWebRequest(asyncWebRequest); asyncManager.registerCallableInterceptors(this.callableInterceptors); asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors); if (asyncManager.hasConcurrentResult()) { Object result = asyncManager.getConcurrentResult(); mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0]; asyncManager.clearConcurrentResult(); requestMappingMethod = requestMappingMethod.wrapConcurrentResult(result); } requestMappingMethod.invokeAndHandle(webRequest, mavContainer); if (asyncManager.isConcurrentHandlingStarted()) { return null; } return getModelAndView(mavContainer, modelFactory, webRequest); }
2 HttpRequestHandlerAdapter
HttpRequestHandlerAdapter 可以执行 HttpRequestHandler 类型的 Handler,源码如下
@Override public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { ((HttpRequestHandler) handler).handleRequest(request, response); return null; }
3 SimpleControllerHandlerAdapter
SimpleControllerHandlerAdapter 可以执行 Controller 类型的 Handler,源码如下
@Override public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return ((Controller) handler).handleRequest(request, response); }
4 SimpleServletHandlerAdapter
SimpleServletHandlerAdapter 可以执行 Servlet 类型的 Handler,源码如下
@Override public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { ((Servlet) handler).service(request, response); return null; }
三、HandlerExceptionResolver
负责处理异常的类,负责根据异常来设置 ModelAndView,然后交由 render 渲染界面。HandlerExecptionResolver 接口中只有一个方法,如下:
- ModelAndView resolveException(HttpServletRequest req, HttpServletResponse res, Object handler, Exception ex);
HandlerMapping
) 映射出来的 handler
对象是不一样的,AbstractUrlHandlerMapping
映射器映射出来的是 handler
是 Controller
对象,AbstractHandlerMethodMapping
映射器映射出来的 handler
是 HandlerMethod
对象。由此我们猜想映射的处理器也应该有很多种,不同的映射由不同的适配器来负责解析。1 HandlerAdapter
基础了解
1.1 首先我们来看下适配器 HandlerAdapter
接口内部的方法
![](https://img2022.cnblogs.com/blog/2084611/202203/2084611-20220308082311969-126204769.png)
1.2 再来看下适配器 HandlerAdapter
接口的实现链
![](https://img2022.cnblogs.com/blog/2084611/202203/2084611-20220308082321671-1793024776.png)
1.3 适配器们的加载
首先我们来看下源码,容器初始化的时候会将注入到容器的适配器们加进缓存。
![](https://img2022.cnblogs.com/blog/2084611/202203/2084611-20220308082331836-1501052018.png)
首先扫描注入容器的适配器,这里需要注意下 <mvc:annotation-driven /> 会帮我们注入 RequestMappingHandlerAdapter
、HttpRequestHandlerAdapter
和 SimpleControllerHandlerAdapter
这三个配置器,我们需要注意下不要手动重复注入。
当我们没有写 <mvc:annotation-driven /> 标签帮我们注入,也没有手动注入,从上面源码最后一步可以看到,容器在初始化的时候检测到会自动帮我们注入 RequestMappingHandlerAdapter
、HttpRequestHandlerAdapter
和 SimpleControllerHandlerAdapter
这三个配置器。
2 HttpRequestHandlerAdapter
可以执行 HttpRequestHandler
类型的 handler
,源码如下
![](https://img2022.cnblogs.com/blog/2084611/202203/2084611-20220308082341999-1633147568.png)
3 SimpleServletHandlerAdapter
可以执行 Servlet
类型的 handler
,源码如下
![](https://img2022.cnblogs.com/blog/2084611/202203/2084611-20220308082349871-1334821579.png)
4 SimpleControllerHandlerAdapter
可以执行 Controller
类型的 handler
,源码如下
![](https://img2022.cnblogs.com/blog/2084611/202203/2084611-20220308082359921-1271976147.png)
在前面 SpringMVC工作原理之处理映射[HandlerMapping] 笔记中使用 AbstractUrlHandlerMapping
的子类映射器最终返回的 handler
是 Controller
类型,当时定义的视图控制器都继承自 AbstractController
,视图必须实现 handleRequestInternal(...)
方法。
在 AbstractController
内部源码如下
![](https://img2022.cnblogs.com/blog/2084611/202203/2084611-20220308082410739-407095871.png)
从源码中可以看出 Controller
对象调用 handlerRequest(..)
方法最终经过处理后还是调用 handleRequestInternal (..)
方法。
5. AbstractHandlerMethodAdapter
在这里 AbstractHandlerMethodAdapter
只有一个实现子类就是 RequestMappingHandlerAdapter
,首先我们来看下其内部是怎么来实现判断 supports(..)
是否支持该 handler
和接下来的 handler
解析方法 handle(..)
的,源码如下
![](https://img2022.cnblogs.com/blog/2084611/202203/2084611-20220308082424234-669866377.png)
6. 总结
关于适配器的分类总结及适配,本篇笔记就记录到这里。前面讲到的几种适配器执行对应的 handler
都很简单,主要是 RequestMappingHandlerAdapter
适配器,该适配从上面可以看出