Spring学习总结(2.3)-Spring MVC:handlerAdapter

    前面一篇博客介绍了HandlerMapping这个组件,它负责的是定位请求处理器Handler。这是SpringMvc处理流程的第二步。那么,当定位到Handler之后,DispatcherServlet会将得到的Handler告知HandlerAdapter,HandlerAdapter再根据请求去定位请求的具体处理方法是哪一个。

职责   

    在HandlerMapping返回处理请求的Controller实例后,需要一个帮助定位具体请求方法的处理类,这个类就是HandlerAdapter,HandlerAdapter是处理器适配器,Spring MVC通过HandlerAdapter来实际调用处理函数。例如Spring MVC自动注册的AnnotationMethodHandlerAdpater,HandlerAdapter定义了如何处理请求的策略,通过请求url、请求Method和处理器的requestMapping定义,最终确定使用处理类的哪个方法来处理请求,并检查处理类相应处理方法的参数以及相关的Annotation配置,确定如何转换需要的参数传入调用方法,并最终调用返回ModelAndView。DispatcherServlet中根据HandlerMapping找到对应的handler method后,首先检查当前工程中注册的所有可用的handlerAdapter,根据handlerAdapter中的supports方法找到可以使用的handlerAdapter。通过调用handlerAdapter中的handler方法来处理及准备handler method的参数及annotation(这就是spring mvc如何将request中的参数变成handle method中的输入参数的地方),最终调用实际的handler method。

handlerAdapter接口      

public abstract interface HandlerAdapter
{
  public abstract boolean supports(Object paramObject);
  
  public abstract ModelAndView handle(HttpServletRequest paramHttpServletRequest, HttpServletResponse paramHttpServletResponse, Object paramObject)
    throws Exception;
  
  public abstract long getLastModified(HttpServletRequest paramHttpServletRequest, Object paramObject);
}

    该接口定义了三个方法,support方法的作用是判断处理适配器是不是支持该Handler。hanle方法,调用对应的Handler中适配到的方法,并返回一个ModelView。第三个方法不确定干嘛用的。

AnnotationMethodHandlerAdpater

supports方法实现

    其中又调用了getMethodResolver这个方法后面又涉及到了很多东西,我看的不是很懂就不往更深的说了。它的主要逻辑是根据传入handler去取得ServletHandlerMethodResolver,这个ServletHandlerMethodResolver的作用可以简单的认为为解析能作为serlvet使用的方法。

public boolean supports(Object handler) {  
        return getMethodResolver(handler).hasHandlerMethods();  
    }  
private ServletHandlerMethodResolver getMethodResolver(Object handler) {  
    Class handlerClass = ClassUtils.getUserClass(handler);  
    ServletHandlerMethodResolver resolver = this.methodResolverCache.get(handlerClass);  
    if (resolver == null) {  
        resolver = new ServletHandlerMethodResolver(handlerClass);  
        this.methodResolverCache.put(handlerClass, resolver);  
    }  
    return resolver;  
}  

handl方法实现

public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)  
            throws Exception {  
  
        if (AnnotationUtils.findAnnotation(handler.getClass(), SessionAttributes.class) != null) {  
            // Always prevent caching in case of session attribute management.  
            checkAndPrepare(request, response, this.cacheSecondsForSessionAttributeHandlers, true);  
            // Prepare cached set of session attributes names.  
        }  
        else {  
            // Uses configured default cacheSeconds setting.  
            checkAndPrepare(request, response, true);  
        }  
  
        // Execute invokeHandlerMethod in synchronized block if required.  
        if (this.synchronizeOnSession) {  
            HttpSession session = request.getSession(false);  
            if (session != null) {  
                Object mutex = WebUtils.getSessionMutex(session);  
                synchronized (mutex) {  
                    return invokeHandlerMethod(request, response, handler);  
                }  
            }  
        }  
  
        return invokeHandlerMethod(request, response, handler);  
    } 

 

这个方法中的重点在于invokeHandlerMethod

protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler)  
            throws Exception {  
  
        ServletHandlerMethodResolver methodResolver = getMethodResolver(handler);  
        Method handlerMethod = methodResolver.resolveHandlerMethod(request);  
        ServletHandlerMethodInvoker methodInvoker = new ServletHandlerMethodInvoker(methodResolver);  
        ServletWebRequest webRequest = new ServletWebRequest(request, response);  
        ExtendedModelMap implicitModel = new BindingAwareModelMap();  
  
        Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel);  
        ModelAndView mav =  
                methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, webRequest);  
        methodInvoker.updateModelAttributes(handler, (mav != null ? mav.getModel() : null), implicitModel, webRequest);  
        return mav;  
    }  

    其实它干的事情就是取得了handler中的对应请求的可执行方法,还是通过getMethodResolver方法实现的。在supports方法中已经构建了,所以这里调用的时候直接去缓存中取得就好了。

   
小结:handlerAdapter这个类的作用就是接过handlermapping解析请求得到的handler对象。在更精确的定位到能够执行请求的方法。

    原文作者:Spring MVC
    原文地址: https://blog.csdn.net/zhuojiajin/article/details/46597687
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞