Spring MVC之适配器的获取及执行(RequestMappingHandlerAdapter)

家资是何物,积帙列梁梠。这篇文章主要讲述Spring MVC之适配器的获取及执行(RequestMappingHandlerAdapter)相关的知识,希望能为你提供帮助。
首先看下doDispatch()方法如何找到适合的适配器来执行方法的:

1protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { 2Iterator i$ = this.handlerAdapters.iterator(); 3 4HandlerAdapter ha; 5do { 6if (!i$.hasNext()) { 7throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler"); 8} 9 10ha = (HandlerAdapter)i$.next(); 11if (this.logger.isTraceEnabled()) { 12this.logger.trace("Testing handler adapter [" + ha + "]"); 13} 14} while(!ha.supports(handler)); //遍历初始化时候保存好的适配器,通过执行每个适配器的supports方法,如果支持就是他了。 15 16return ha; 17}

注: 这块也有点责任链模式的意思...
【Spring MVC之适配器的获取及执行(RequestMappingHandlerAdapter)】下面看下RequestMappingHandlerAdapter是怎么实现support方法的,看之前先上类图。
Spring MVC之适配器的获取及执行(RequestMappingHandlerAdapter)

文章图片

实际上support方法是在AbstractHandlerMethodAdapter这个父类实现的,然后给自己留个钩子方法,让子类实现
1public final boolean supports(Object handler) { 2return handler instanceof HandlerMethod & & this.supportsInternal((HandlerMethod)handler); 3} 4 5protected abstract boolean supportsInternal(HandlerMethod var1); //钩子方法

这里RequestMappingHandlerAdapter的supportInternal直接是返回的true,估计后续扩展其他子类可能会复杂些,这就是设计模式的好处。
这样就找到了合适的适配器,下面来看执行:
1protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { 2HttpServletRequest processedRequest = request; 3HandlerExecutionChain mappedHandler = null; 4boolean multipartRequestParsed = false; 5WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); 6 7try { 8try { 9ModelAndView mv = null; 10Exception dispatchException = null; 11 12try { 13processedRequest = this.checkMultipart(request); 14multipartRequestParsed = processedRequest != request; 15mappedHandler = this.getHandler(processedRequest, false); //获取处理器 16if (mappedHandler == null || mappedHandler.getHandler() == null) { 17this.noHandlerFound(processedRequest, response); 18return; 19} 20 21HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler()); //获取适配器 22String method = request.getMethod(); 23boolean isGet = "GET".equals(method); 24if (isGet || "HEAD".equals(method)) { 25long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); 26if (this.logger.isDebugEnabled()) { 27String requestUri = urlPathHelper.getRequestUri(request); 28this.logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified); 29} 30 31if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) & & isGet) { 32return; 33} 34} //这一块是处理重复请求??? 有大神知道请留言.... 35 36if (!mappedHandler.applyPreHandle(processedRequest, response)) { 37return; 38} //执行拦截器的preHandle方法 39 40try { 41mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); //执行真正的Controller方法,就是我们的方法 42} finally { 43if (asyncManager.isConcurrentHandlingStarted()) { 44return; 45} 46 47} 48 49this.applyDefaultViewName(request, mv); //设置视图名称 50mappedHandler.applyPostHandle(processedRequest, response, mv); //执行拦截器的postHandle方法 51} catch (Exception var28) { 52dispatchException = var28; 53} 54 55this.processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); //渲染视图 56} catch (Exception var29) { 57this.triggerAfterCompletion(processedRequest, response, mappedHandler, var29); 58} catch (Error var30) { 59this.triggerAfterCompletionWithError(processedRequest, response, mappedHandler, var30); 60} 61 62} finally { 63if (asyncManager.isConcurrentHandlingStarted()) { 64mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); //执行拦截器的afterConcurrentHandlingStarted 65return; 66} else { 67if (multipartRequestParsed) { 68this.cleanupMultipart(processedRequest); 69} 70 71} 72} 73}

拦截器这里就不在多说,这块就是返回false就不在往下执行。下面我们重点满ha.handle()方法,是如果映射参数,找到我们的方法,封装结果的。
类图前面已经展示了,实际上handle是在父类AbstractHandlerMethodAdapter实现的
1public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 2return this.handleInternal(request, response, (HandlerMethod)handler); //子类实现这个方法 3} 4 5protected abstract ModelAndView handleInternal(HttpServletRequest var1, HttpServletResponse var2, HandlerMethod var3) throws Exception;

1protected final ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { 2if (this.getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) { 3this.checkAndPrepare(request, response, this.cacheSecondsForSessionAttributeHandlers, true); 4} else { 5this.checkAndPrepare(request, response, true); 6} //看代码应该是从session中获取一些信息,然后初始化header等信息,不知道准确不?请大家指正! 7//这块就是根据需要是否进行同步操作 8if (this.synchronizeOnSession) { 9HttpSession session = request.getSession(false); 10if (session != null) { 11Object mutex = WebUtils.getSessionMutex(session); 12synchronized(mutex) { 13return this.invokeHandleMethod(request, response, handlerMethod); 14} 15} 16} 17//正式进入执行环节 18return this.invokeHandleMethod(request, response, handlerMethod); 19}

下面这个方法非常重要,将重点讲解:
1private ModelAndView invokeHandleMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { 2ServletWebRequest webRequest = new ServletWebRequest(request, response); 3WebDataBinderFactory binderFactory = this.getDataBinderFactory(handlerMethod); //创建@InitBinder注解的方法的工厂类,进行缓存 4ModelFactory modelFactory = this.getModelFactory(handlerMethod, binderFactory); //创建@ModelAttribute@ControllerAdvice注解方法工厂并缓存 5ServletInvocableHandlerMethod requestMappingMethod = this.createRequestMappingMethod(handlerMethod, binderFactory); 6ModelAndViewContainer mavContainer = new ModelAndViewContainer(); //创建结果容器并初始化一些参数, 7mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request)); 8modelFactory.initModel(webRequest, mavContainer, requestMappingMethod); //执行@ModelAttribute注解的方法,将结果放到结果容器中 9mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect); 10AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response); //下面异步这一块不太明白,等后续在慢慢分析 11asyncWebRequest.setTimeout(this.asyncRequestTimeout); 12WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); 13asyncManager.setTaskExecutor(this.taskExecutor); 14asyncManager.setAsyncWebRequest(asyncWebRequest); 15asyncManager.registerCallableInterceptors(this.callableInterceptors); 16asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors); 17if (asyncManager.hasConcurrentResult()) { 18Object result = asyncManager.getConcurrentResult(); 19mavContainer = (ModelAndViewContainer)asyncManager.getConcurrentResultContext()[0]; 20asyncManager.clearConcurrentResult(); 21if (this.logger.isDebugEnabled()) { 22this.logger.debug("Found concurrent result value [" + result + "]"); 23} 24 25requestMappingMethod = requestMappingMethod.wrapConcurrentResult(result); 26} 27 28requestMappingMethod.invokeAndHandle(webRequest, mavContainer, new Object[0]); //继续执行方法 29return asyncManager.isConcurrentHandlingStarted() ? null : this.getModelAndView(mavContainer, modelFactory, webRequest); //返回值了,两种情况 30}

1public final void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { 2Object returnValue = https://www.songbingjia.com/android/this.invokeForRequest(webRequest, mavContainer, providedArgs); //执行方法,获取返回值 3this.setResponseStatus(webRequest); 4if (returnValue == null) { 5if (this.isRequestNotModified(webRequest) || this.hasResponseStatus() || mavContainer.isRequestHandled()) { 6mavContainer.setRequestHandled(true); 7return; 8} 9} else if (StringUtils.hasText(this.responseReason)) { 10mavContainer.setRequestHandled(true); 11return; 12} 13 14mavContainer.setRequestHandled(false); 15 16try { //处理返回值 ,封装结果集 17this.returnValueHandlers.handleReturnValue(returnValue, this.getReturnValueType(returnValue), mavContainer, webRequest); 18} catch (Exception var6) { 19if (this.logger.isTraceEnabled()) { 20this.logger.trace(this.getReturnValueHandlingErrorMessage("Error handling return value", returnValue), var6); 21} 22 23throw var6; 24} 25}

1public final Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { 2Object[] args = this.getMethodArgumentValues(request, mavContainer, providedArgs); //处理 参数 3if (this.logger.isTraceEnabled()) { 4StringBuilder builder = new StringBuilder("Invoking ["); 5builder.append(this.getMethod().getName()).append("] method with arguments "); 6builder.append(Arrays.asList(args)); 7this.logger.trace(builder.toString()); 8} 9 10Object returnValue = https://www.songbingjia.com/android/this.invoke(args); //反射执行方法 11if (this.logger.isTraceEnabled()) { 12this.logger.trace("Method [" + this.getMethod().getName() + "] returned [" + returnValue + "]"); 13} 14 15return returnValue; 16}

1private Object[] getMethodArgumentValues(NativeWebRequest request, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { 2MethodParameter[] parameters = this.getMethodParameters(); 3Object[] args = new Object[parameters.length]; 4 5for(int i = 0; i < parameters.length; ++i) { //遍历方法的所有参数 6MethodParameter parameter = parameters[i]; 7parameter.initParameterNameDiscovery(this.parameterNameDiscoverer); 8GenericTypeResolver.resolveParameterType(parameter, this.getBean().getClass()); //获取设置参数类型 9args[i] = this.resolveProvidedArgument(parameter, providedArgs); 10if (args[i] == null) { 11if (this.argumentResolvers.supportsParameter(parameter)) { //这块是遍历预置的参数解析器,就是前面说的责任链模式,**composite负责查找和执行 12try { //由找到的参数解析器,来解析参数 13args[i] = this.argumentResolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory); 14} catch (Exception var9) { 15if (this.logger.isTraceEnabled()) { 16this.logger.trace(this.getArgumentResolutionErrorMessage("Error resolving argument", i), var9); 17} 18 19throw var9; 20} 21} else if (args[i] == null) { 22String msg = this.getArgumentResolutionErrorMessage("No suitable resolver for argument", i); 23throw new IllegalStateException(msg); 24} 25} 26} 27 28return args; 29}

这块以,没有任何注解,参数为javaBean的解析器为例:ModelAttributeMethodProcessor
1public boolean supportsParameter(MethodParameter parameter) { 2if (parameter.hasParameterAnnotation(ModelAttribute.class)) { 3return true; 4} else if (this.annotationNotRequired) { 5return !BeanUtils.isSimpleProperty(parameter.getParameterType()); 6} else { 7return false; 8} 9} 10 11public final Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest request, WebDataBinderFactory binderFactory) throws Exception { 12String name = ModelFactory.getNameForParameter(parameter); //如果当前参数用@ModelAttribute修饰了,返回value值或者参数类型第一个字母小写 13// 获取需要绑定的表单对象,看参数容器包含name为key的对象不,有的话就用它,没有创建个新的。
Object attribute = mavContainer.containsAttribute(name) ? mavContainer.getModel().get(name) : this.createAttribute(name, parameter, binderFactory, request); 14WebDataBinder binder = binderFactory.createBinder(request, attribute, name); 15if (binder.getTarget() != null) { 16this.bindRequestParameters(binder, request); 17this.validateIfApplicable(binder, parameter); 18if (binder.getBindingResult().hasErrors() & & this.isBindExceptionRequired(binder, parameter)) { 19throw new BindException(binder.getBindingResult()); 20} 21} 22//以上就是参数绑定, 这块领开一篇文章详细说 23Map< String, Object> bindingResultModel = binder.getBindingResult().getModel(); 24mavContainer.removeAttributes(bindingResultModel); 25mavContainer.addAllAttributes(bindingResultModel); 26return binder.getTarget(); 27}

参数就这样遍历处理,然后就开始通过反射 invoke执行了。接下来我们看是怎么封装换回结果的
1try { 2this.returnValueHandlers.handleReturnValue(returnValue, this.getReturnValueType(returnValue), mavContainer, webRequest); 3} catch (Exception var6) { 4if (this.logger.isTraceEnabled()) { 5this.logger.trace(this.getReturnValueHandlingErrorMessage("Error handling return value", returnValue), var6); 6} 7 8throw var6; 9}

this.returnValuehandlers. 就是那个返回结果的包装类,初始化的结果解析器就保存这里,处理思路和参数解析器一样的,
1public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { 2HandlerMethodReturnValueHandler handler = this.getReturnValueHandler(returnType); 3Assert.notNull(handler, "Unknown return value type [" + returnType.getParameterType().getName() + "]"); 4handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest); 5} 6 7private HandlerMethodReturnValueHandler getReturnValueHandler(MethodParameter returnType) { 8Iterator i$ = this.returnValueHandlers.iterator(); 9 10HandlerMethodReturnValueHandler returnValueHandler; 11do { 12if (!i$.hasNext()) { 13return null; 14} 15 16returnValueHandler = (HandlerMethodReturnValueHandler)i$.next(); 17if (this.logger.isTraceEnabled()) { 18this.logger.trace("Testing if return value handler [" + returnValueHandler + "] supports [" + returnType.getGenericParameterType() + "]"); 19} 20} while(!returnValueHandler.supportsReturnType(returnType)); 21 22return returnValueHandler; 23}

遍历预置的所有结果解析器,结果解析器统一实现HandlerMethodReturnValueHandler 接口,实现supportReturnType方法:
这里我们距离用@ResponseBody注解的结果解析器RequestResponseBodyMethodProcessor 前面说了,参数和结果集他都实现了
1public boolean supportsReturnType(MethodParameter returnType) { 2return returnType.getMethodAnnotation(ResponseBody.class) != null; //判断是否有@ResponseBody注解 3} 4public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws IOException, HttpMediaTypeNotAcceptableException { 5mavContainer.setRequestHandled(true); 6if (returnValue != null) { 7this.writeWithMessageConverters(returnValue, returnType, webRequest); //用内置的消息转换器来转换结果集 8} 9 10}

这里可能有人会问,消息转换器什么时候加载的?是在RequestMappingHandlerAdapter这个bean实例化的时候加载的,同时加载参数和结果解析器时候注入到解析器当中的
1public RequestMappingHandlerAdapter() { //无参构造函数中初始化 2StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(); 3stringHttpMessageConverter.setWriteAcceptCharset(false); 4this.messageConverters = new ArrayList(); 5this.messageConverters.add(new ByteArrayHttpMessageConverter()); 6this.messageConverters.add(stringHttpMessageConverter); 7this.messageConverters.add(new SourceHttpMessageConverter()); 8this.messageConverters.add(new AllEncompassingFormHttpMessageConverter()); 9} 10private List< HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() { //构造参数解析器时候,注入进去 11List< HandlerMethodReturnValueHandler> handlers = new ArrayList(); 12handlers.add(new ModelAndViewMethodReturnValueHandler()); 13handlers.add(new ModelMethodProcessor()); 14handlers.add(new ViewMethodReturnValueHandler()); 15handlers.add(new HttpEntityMethodProcessor(this.getMessageConverters(), this.contentNegotiationManager)); 16handlers.add(new CallableMethodReturnValueHandler()); 17handlers.add(new DeferredResultMethodReturnValueHandler()); 18handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory)); 19handlers.add(new ModelAttributeMethodProcessor(false)); 20handlers.add(new RequestResponseBodyMethodProcessor(this.getMessageConverters(), this.contentNegotiationManager)); 21handlers.add(new ViewNameMethodReturnValueHandler()); 22handlers.add(new MapMethodProcessor()); 23if (this.getCustomReturnValueHandlers() != null) { 24handlers.addAll(this.getCustomReturnValueHandlers()); 25} 26 27if (!CollectionUtils.isEmpty(this.getModelAndViewResolvers())) { 28handlers.add(new ModelAndViewResolverMethodReturnValueHandler(this.getModelAndViewResolvers())); 29} else {

    推荐阅读