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 映射器映射出来的是 handlerController 对象,AbstractHandlerMethodMapping 映射器映射出来的 handlerHandlerMethod 对象。由此我们猜想映射的处理器也应该有很多种,不同的映射由不同的适配器来负责解析。

1 HandlerAdapter 基础了解

1.1 首先我们来看下适配器 HandlerAdapter 接口内部的方法

 

 

1.2 再来看下适配器 HandlerAdapter 接口的实现链

 

 

1.3 适配器们的加载

首先我们来看下源码,容器初始化的时候会将注入到容器的适配器们加进缓存。

 

 

首先扫描注入容器的适配器,这里需要注意下 <mvc:annotation-driven /> 会帮我们注入 RequestMappingHandlerAdapterHttpRequestHandlerAdapterSimpleControllerHandlerAdapter 这三个配置器,我们需要注意下不要手动重复注入。
当我们没有写 <mvc:annotation-driven /> 标签帮我们注入,也没有手动注入,从上面源码最后一步可以看到,容器在初始化的时候检测到会自动帮我们注入 RequestMappingHandlerAdapterHttpRequestHandlerAdapterSimpleControllerHandlerAdapter 这三个配置器。

2 HttpRequestHandlerAdapter

可以执行 HttpRequestHandler 类型的 handler,源码如下

 

 

3 SimpleServletHandlerAdapter

可以执行 Servlet 类型的 handler,源码如下

 

 

4 SimpleControllerHandlerAdapter

可以执行 Controller 类型的 handler,源码如下

 

 

在前面 SpringMVC工作原理之处理映射[HandlerMapping] 笔记中使用 AbstractUrlHandlerMapping 的子类映射器最终返回的 handlerController 类型,当时定义的视图控制器都继承自 AbstractController,视图必须实现 handleRequestInternal(...) 方法。
AbstractController 内部源码如下

 

 

从源码中可以看出 Controller 对象调用 handlerRequest(..) 方法最终经过处理后还是调用 handleRequestInternal (..) 方法。

5. AbstractHandlerMethodAdapter

在这里 AbstractHandlerMethodAdapter 只有一个实现子类就是 RequestMappingHandlerAdapter,首先我们来看下其内部是怎么来实现判断 supports(..) 是否支持该 handler 和接下来的 handler 解析方法 handle(..) 的,源码如下

 

 

 

6. 总结

关于适配器的分类总结及适配,本篇笔记就记录到这里。前面讲到的几种适配器执行对应的 handler 都很简单,主要是 RequestMappingHandlerAdapter 适配器,该适配从上面可以看出

 

posted @ 2022-03-08 08:25  hanease  阅读(46)  评论(0编辑  收藏  举报