HandlerAdapter工作流程,运行原理

HandlerAdapter是处理适配器,它调用具体的方法对用户发来的请求来进行处理。SpringMVC 通过HandlerAdapter的handler方法来调用请求处理函数,它的工作运行原理如下。

工作流程概述

1.DispatcherServlte会根据配置文件信息注册HandlerAdapter,如果在配置文件中没有配置,那么 DispatcherServlte会获取HandlerAdapter的默认配置,如果是读取默认配置的话,DispatcherServlte会读取 DispatcherServlte.properties文件,该文件中配置了三种 HandlerAdapter:HttpRequestHandlerAdapter,SimpleControllerHandlerAdapter和 AnnotationMethodHandlerAdapter。DispatcherServlte会将这三个HandlerAdapter对象存储到 它的handlerAdapters这个集合属性中,这样就完成了HandlerAdapter的注册。

2.DispatcherServlte会根据handlerMapping传过来的controller与已经注册好了的HandlerAdapter 一一匹配,看哪一种HandlerAdapter是支持该controller类型的,如果找到了其中一种HandlerAdapter是支持传过来的 controller类型,那么该HandlerAdapter会调用自己的handle方法,handle方法运用Java的 反射机制执行controller的具体方法来获得ModelAndView,例如SimpleControllerHandlerAdapter是支持 实现了controller接口的控制器,如果自己写的控制器实现了controller接口,那么 SimpleControllerHandlerAdapter就会去执行自己写控制器中的具体方法来完成请求。

HandlerAdapter工作流程图

流程说明

1. AbstractHandlerMethodAdapter

该类是HandlerAdapter接口的简单抽象类,实现了接口定义的方法。但也并未做真正的实现,而是留给了子类。

详细说明可以看 AbstractHandlerMethodAdapter类详解 - HandlerAdapter系列二

2. RequestMappingHandlerAdapter

该类继承了 AbstractHandlerMethodAdapter 类,真正意义上实现了 HandlerAdapter 接口定义的功能。

该方法的具体过程如下:

1.校验请求,即检查是否支持当前 rqeuest 的 method 和 session

2.判断控制器是否存在 @SessionAttributes 注解,有则设置缓存,否则准备响应

3.处理器调用,返回 ModelAndView 。

详细类说明可以看 RequestMappingHandlerAdapter类详解 - HandlerAdapter系列三

3. ServletInvocableHandlerMethod

该类实现了 HandlerMethod 类,HandlerMethod创建ServletInvocableHandlerMethod,接下来调用ServletInvocableHandlerMethod的invokeAndHandle方法,其实最终是通过反射机制调用Controller中的方法。

详细类说明可以看 ServletInvocableHandlerMethod类详解 - HandlerAdapter系列七

4. 处理器调用invokeHandlerMethod方法

protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, 
    HandlerMethod handlerMethod) throws Exception {

    ServletWebRequest webRequest = new ServletWebRequest(request, response);

    // 1.数据绑定
    WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);

    // 2.创建 ModelFactory 
    // 添加了 @ModelAttribute,@SessionAttributes 等注解内容
    ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);

    // 3.创建 ServletInvocableHandlerMethod,并绑定相关属性
    ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
    invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
    invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
    invocableMethod.setDataBinderFactory(binderFactory);
    invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);

    // 4.创建 ModelAndViewContainer
    ModelAndViewContainer mavContainer = new ModelAndViewContainer();
    mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
    modelFactory.initModel(webRequest, mavContainer, invocableMethod);
    mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);

    // 省略部分源码...

    // 5.调用控制器方法
    invocableMethod.invokeAndHandle(webRequest, mavContainer);


    // 6.返回 ModelAndView
    return getModelAndView(mavContainer, modelFactory, webRequest);
}

5. getModelAndView方法

private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,ModelFactory modelFactory, 
    NativeWebRequest webRequest) throws Exception {

    // 更新 Mdoel 
    modelFactory.updateModel(webRequest, mavContainer);

    // 判断请求是否处理器完毕
    if (mavContainer.isRequestHandled()) {
        return null;
    }

    // 关键 -> 创建 ModelAndView
    ModelMap model = mavContainer.getModel();
    ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model);

    // 判断 view 是不是字符串
    if (!mavContainer.isViewReference()) {
        mav.setView((View) mavContainer.getView());
    }

    // 重定向相关
    if (model instanceof RedirectAttributes) {
        Map flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
        RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
    }

    return mav;
}

版权声明:本文为JAVASCHOOL原创文章,未经本站允许不得转载。