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
接口内部的方法
1.2 再来看下适配器 HandlerAdapter
接口的实现链
1.3 适配器们的加载
首先我们来看下源码,容器初始化的时候会将注入到容器的适配器们加进缓存。
首先扫描注入容器的适配器,这里需要注意下 <mvc:annotation-driven /> 会帮我们注入 RequestMappingHandlerAdapter
、HttpRequestHandlerAdapter
和 SimpleControllerHandlerAdapter
这三个配置器,我们需要注意下不要手动重复注入。
当我们没有写 <mvc:annotation-driven /> 标签帮我们注入,也没有手动注入,从上面源码最后一步可以看到,容器在初始化的时候检测到会自动帮我们注入 RequestMappingHandlerAdapter
、HttpRequestHandlerAdapter
和 SimpleControllerHandlerAdapter
这三个配置器。
2 HttpRequestHandlerAdapter
可以执行 HttpRequestHandler
类型的 handler
,源码如下
3 SimpleServletHandlerAdapter
可以执行 Servlet
类型的 handler
,源码如下
4 SimpleControllerHandlerAdapter
可以执行 Controller
类型的 handler
,源码如下
在前面 SpringMVC工作原理之处理映射[HandlerMapping] 笔记中使用 AbstractUrlHandlerMapping
的子类映射器最终返回的 handler
是 Controller
类型,当时定义的视图控制器都继承自 AbstractController
,视图必须实现 handleRequestInternal(...)
方法。
在 AbstractController
内部源码如下
从源码中可以看出 Controller
对象调用 handlerRequest(..)
方法最终经过处理后还是调用 handleRequestInternal (..)
方法。
5. AbstractHandlerMethodAdapter
在这里 AbstractHandlerMethodAdapter
只有一个实现子类就是 RequestMappingHandlerAdapter
,首先我们来看下其内部是怎么来实现判断 supports(..)
是否支持该 handler
和接下来的 handler
解析方法 handle(..)
的,源码如下
6. 总结
关于适配器的分类总结及适配,本篇笔记就记录到这里。前面讲到的几种适配器执行对应的 handler
都很简单,主要是 RequestMappingHandlerAdapter
适配器,该适配从上面可以看出