前面一篇博客介绍了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对象。在更精确的定位到能够执行请求的方法。