handleInternal
使用给定的处理器方法处理请求。
AbstractHandlerMethodAdapter
中定义的 protected 抽象方法,专门由该子类实现。
开始处理请求,返回一个ModelAndView。
@Override protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ModelAndView mav; checkRequest(request); // 如果需要,在同步块中执行invokeHandlerMethod,默认不 if (this.synchronizeOnSession) { HttpSession session = request.getSession(false); if (session != null) { Object mutex = WebUtils.getSessionMutex(session); synchronized (mutex) { mav = invokeHandlerMethod(request, response, handlerMethod); } } else { // No HttpSession available -> no mutex necessary mav = invokeHandlerMethod(request, response, handlerMethod); } } else { // No synchronization on session demanded at all... mav = invokeHandlerMethod(request, response, handlerMethod); } // 处理Cache-Control请求头(若你没有set if (!response.containsHeader(HEADER_CACHE_CONTROL)) { if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) { applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers); } else { prepareResponse(response); } } return mav; }
剩下的便是本适配器最为重要的一个方法:invokeHandlerMethod():
// 它的作用就是执行目标的HandlerMethod,然后返回一个ModelAndView @Nullable protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ServletWebRequest webRequest = new ServletWebRequest(request, response); // 注意:此处只有try-finally 哦 // 因为invocableMethod.invokeAndHandle(webRequest, mavContainer)是可能会抛出异常的(交给全局异常处理) try { // 最终创建的是一个ServletRequestDataBinderFactory,持有所有@InitBinder的method方法们 WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod); // 创建一个ModelFactory,@ModelAttribute啥的方法就会被引用进来 ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory); // 把HandlerMethod包装为ServletInvocableHandlerMethod,具有invoke执行的能力喽 // 下面这几部便是一直给invocableMethod的各大属性赋值~~~ ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod); if (this.argumentResolvers != null) { invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers); } if (this.returnValueHandlers != null) { invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers); } invocableMethod.setDataBinderFactory(binderFactory); invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer); ModelAndViewContainer mavContainer = new ModelAndViewContainer(); // 把上个request里的值放进来到本request里 mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request)); // model工厂:把它里面的Model值放进mavContainer容器内(此处@ModelAttribute/@SessionAttribute啥的生效) modelFactory.initModel(webRequest, mavContainer, invocableMethod); mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect); AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response); asyncWebRequest.setTimeout(this.asyncRequestTimeout); WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); asyncManager.setTaskExecutor(this.taskExecutor); asyncManager.setAsyncWebRequest(asyncWebRequest); asyncManager.registerCallableInterceptors(this.callableInterceptors); asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors); // 它不管是不是异步请求都先用AsyncWebRequest 包装了一下,但是若是同步请求 // asyncManager.hasConcurrentResult()肯定是为false的~~~ if (asyncManager.hasConcurrentResult()) { Object result = asyncManager.getConcurrentResult(); mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0]; asyncManager.clearConcurrentResult(); LogFormatUtils.traceDebug(logger, traceOn -> { String formatted = LogFormatUtils.formatValue(result, !traceOn); return "Resume with async result [" + formatted + "]"; }); invocableMethod = invocableMethod.wrapConcurrentResult(result); } // 此处其实就是调用ServletInvocableHandlerMethod#invokeAndHandle()方法喽 // 关于它你可以来这里:https://fangshixiang.blog.csdn.net/article/details/98385163 // 注意哦:任何HandlerMethod执行完后都是把结果放在了mavContainer里(它可能有Model,可能有View,可能啥都木有~~) // 因此最后的getModelAndView()又得一看 invocableMethod.invokeAndHandle(webRequest, mavContainer); if (asyncManager.isConcurrentHandlingStarted()) { return null; } return getModelAndView(mavContainer, modelFactory, webRequest); } finally { webRequest.requestCompleted(); } } 任何处理器执行完后,最终返回的的都是一个ModelAndView对象,这得益于getModelAndView()这个方法的适配处理: // @Nullable:表示它返回的可以是个null哦~(若木有视图,就直接不会render啦~因为response已经写入过值了) @Nullable private ModelAndView getModelAndView(ModelAndViewContainer mavContainer, ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception { // 把session里面的内容写入 modelFactory.updateModel(webRequest, mavContainer); // Tips:若已经被处理过,那就返回null喽~~(比如若是@ResponseBody这种,这里就是true) if (mavContainer.isRequestHandled()) { return null; } // 通过View、Model、Status构造出一个ModelAndView,最终就可以完成渲染了 ModelMap model = mavContainer.getModel(); ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus()); if (!mavContainer.isViewReference()) { // 是否是String类型 mav.setView((View) mavContainer.getView()); } // 对重定向RedirectAttributes参数的支持(两个请求之间传递参数,使用的是ATTRIBUTE) if (model instanceof RedirectAttributes) { Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes(); HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); if (request != null) { RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes); } } return mav; }
执行完HandlerMethod后得到一个ModelAndView,它可能是null(比如已被处理过),那最终交给DispatcherServlet就没有后续处理了,否则会做视图渲染:render()。
Spring MVC默认装配了哪些HandlerAdapter呢?
开启@EnableWebMvc:
总结
RequestMappingHandlerAdapter作为HandlerAdapter适配模式的实现,由于@RequestMapping成为了使用Spring MVC的几乎唯一选择,所以它成为了实际意义上的标准实现