处理器适配器接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 // HandlerAdapter.java public interface HandlerAdapter { /** * 是否支持该处理器 */ boolean supports(Object handler); /** * 执行处理器,返回 ModelAndView 结果 */ @Nullable ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception; /** * 返回请求的最新更新时间。 * * 如果不支持该操作,则返回 -1 即可 */ long getLastModified(HttpServletRequest request, Object handler); }
因为,处理器 handler 的类型是 Object 类型,需要有一个调用者来实现 handler 是怎么被使用,怎么被执行。而 HandlerAdapter 的用途就在于此。
HandlerAdapter 整体类图:
SimpleControllerHandlerAdapter 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 // SimpleControllerHandlerAdapter.java public class SimpleControllerHandlerAdapter implements HandlerAdapter { @Override public boolean supports(Object handler) { // <1> 判断是 Controller 类型 return (handler instanceof Controller); } @Override @Nullable public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // <2> Controller 类型的调用 return ((Controller) handler).handleRequest(request, response); } @Override public long getLastModified(HttpServletRequest request, Object handler) { // 处理器实现了 LastModified 接口的情况下 if (handler instanceof LastModified) { return ((LastModified) handler).getLastModified(request); } return -1L; } }
判断处理器 handler 是 Controller 类型。注意,不是 @Controller 注解。
Controller 类型的调用。
HttpRequestHandlerAdapter 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 // HttpRequestHandlerAdapter.java public class HttpRequestHandlerAdapter implements HandlerAdapter { @Override public boolean supports(Object handler) { // 判断是 HttpRequestHandler 类型 return (handler instanceof HttpRequestHandler); } @Override @Nullable public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // HttpRequestHandler 类型的调用 ((HttpRequestHandler) handler).handleRequest(request, response); return null; } @Override public long getLastModified(HttpServletRequest request, Object handler) { // 处理器实现了 LastModified 接口的情况下 if (handler instanceof LastModified) { return ((LastModified) handler).getLastModified(request); } return -1L; } }
类似simple方式
SimpleServletHandlerAdapter 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 // SimpleServletHandlerAdapter.java public class SimpleServletHandlerAdapter implements HandlerAdapter { @Override public boolean supports(Object handler) { // 判断是 Servlet 类型 return (handler instanceof Servlet); } @Override @Nullable public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // Servlet 类型的调用 ((Servlet) handler).service(request, response); return null; } @Override public long getLastModified(HttpServletRequest request, Object handler) { return -1; } }
AbstractHandlerMethodAdapter 实现 HandlerAdapter、Ordered 接口,继承 WebContentGenerator 抽象类,基于 org.springframework.web.method.HandlerMethod 的 HandlerMethodAdapter 抽象类
构造方法 1 2 3 4 5 6 7 8 private int order = Ordered.LOWEST_PRECEDENCE; public AbstractHandlerMethodAdapter() { // no restriction of HTTP methods by default // 调用 WebContentGenerator 类的构造方法 // 参数 restrictDefaultSupportedMethods 参数为 false ,表示不需要严格校验 HttpMethod super(false); }
supports 支持 HandlerMethod 类型的处理器
1 2 3 4 @Override public final boolean supports(Object handler) { return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler)); }
1 protected abstract boolean supportsInternal(HandlerMethod handlerMethod);
handle 处理器请求
1 2 3 4 5 6 7 8 9 @Override @Nullable public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return handleInternal(request, response, (HandlerMethod) handler); } protected abstract ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception;
handleInternal 关于 RequestMappingHandlerAdapter 类对该方法的实现
getLastModified 获得最后更新时间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 // AbstractHandlerMethodAdapter.java @Override public final long getLastModified(HttpServletRequest request, Object handler) { return getLastModifiedInternal(request, (HandlerMethod) handler); } /** * Same contract as for {@link javax.servlet.http.HttpServlet#getLastModified(HttpServletRequest)}. * @param request current HTTP request * @param handlerMethod handler method to use * @return the lastModified value for the given handler */ protected abstract long getLastModifiedInternal(HttpServletRequest request, HandlerMethod handlerMethod);
RequestMappingHandlerAdapter 实现 BeanFactoryAware、InitializingBean 接口,继承 AbstractHandlerMethodAdapter 抽象类,基于 @RequestMapping 注解的 HandlerMethod 的 HandlerMethodAdapter 实现类。
构造方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 /** * MethodFilter that matches {@link InitBinder @InitBinder} methods. */ public static final MethodFilter INIT_BINDER_METHODS = method -> AnnotatedElementUtils.hasAnnotation(method, InitBinder.class); /** * MethodFilter that matches {@link ModelAttribute @ModelAttribute} methods. */ public static final MethodFilter MODEL_ATTRIBUTE_METHODS = method -> (!AnnotatedElementUtils.hasAnnotation(method, RequestMapping.class) && AnnotatedElementUtils.hasAnnotation(method, ModelAttribute.class)); @Nullable private List<HandlerMethodArgumentResolver> customArgumentResolvers; @Nullable private HandlerMethodArgumentResolverComposite argumentResolvers; @Nullable private HandlerMethodArgumentResolverComposite initBinderArgumentResolvers; @Nullable private List<HandlerMethodReturnValueHandler> customReturnValueHandlers; @Nullable private HandlerMethodReturnValueHandlerComposite returnValueHandlers; @Nullable private List<ModelAndViewResolver> modelAndViewResolvers; private ContentNegotiationManager contentNegotiationManager = new ContentNegotiationManager(); private List<HttpMessageConverter<?>> messageConverters; private List<Object> requestResponseBodyAdvice = new ArrayList<>(); @Nullable private WebBindingInitializer webBindingInitializer; private AsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor("MvcAsync"); @Nullable private Long asyncRequestTimeout; private CallableProcessingInterceptor[] callableInterceptors = new CallableProcessingInterceptor[0]; private DeferredResultProcessingInterceptor[] deferredResultInterceptors = new DeferredResultProcessingInterceptor[0]; private ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance(); private boolean ignoreDefaultModelOnRedirect = false; private int cacheSecondsForSessionAttributeHandlers = 0; /** * 是否对相同 Session 加锁 */ private boolean synchronizeOnSession = false; private SessionAttributeStore sessionAttributeStore = new DefaultSessionAttributeStore(); private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer(); @Nullable private ConfigurableBeanFactory beanFactory; // ========== 缓存 ========== private final Map<Class<?>, SessionAttributesHandler> sessionAttributesHandlerCache = new ConcurrentHashMap<>(64); private final Map<Class<?>, Set<Method>> initBinderCache = new ConcurrentHashMap<>(64); private final Map<ControllerAdviceBean, Set<Method>> initBinderAdviceCache = new LinkedHashMap<>(); private final Map<Class<?>, Set<Method>> modelAttributeCache = new ConcurrentHashMap<>(64); private final Map<ControllerAdviceBean, Set<Method>> modelAttributeAdviceCache = new LinkedHashMap<>(); public RequestMappingHandlerAdapter() { // 初始化 messageConverters StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(); stringHttpMessageConverter.setWriteAcceptCharset(false); // see SPR-7316 this.messageConverters = new ArrayList<>(4); this.messageConverters.add(new ByteArrayHttpMessageConverter()); this.messageConverters.add(stringHttpMessageConverter); try { this.messageConverters.add(new SourceHttpMessageConverter<>()); } catch (Error err) { // Ignore when no TransformerFactory implementation is available } this.messageConverters.add(new AllEncompassingFormHttpMessageConverter()); }
afterPropertiesSet 进一步初始化 RequestMappingHandlerAdapter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @Override public void afterPropertiesSet() { // Do this first, it may add ResponseBody advice beans // <1> 初始化 ControllerAdvice 相关 initControllerAdviceCache(); // <2> 初始化 argumentResolvers 属性 if (this.argumentResolvers == null) { List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers(); this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers); } // <3> 初始化 initBinderArgumentResolvers 属性 if (this.initBinderArgumentResolvers == null) { List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers(); this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers); } // <4> 初始化 returnValueHandlers 属性 if (this.returnValueHandlers == null) { List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers(); this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers); } }
初始化 ControllerAdvice 相关
初始化 argumentResolvers 属性,getDefaultArgumentResolvers() 方法,获得默认的 HandlerMethodArgumentResolver 数组
初始化 initBinderArgumentResolvers 属性,getDefaultInitBinderArgumentResolvers() 方法,获得默认的 HandlerMethodArgumentResolver 数组
初始化 returnValueHandlers 属性。其中,#getDefaultReturnValueHandlers() 方法,获得默认的 HandlerMethodReturnValueHandler 数组。
initControllerAdviceCache 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 private void initControllerAdviceCache() { if (getApplicationContext() == null) { return; } // <1> 扫描 @ControllerAdvice 注解的 Bean 们,并将进行排序 List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext()); AnnotationAwareOrderComparator.sort(adviceBeans); List<Object> requestResponseBodyAdviceBeans = new ArrayList<>(); // <2> 遍历 ControllerAdviceBean 数组 for (ControllerAdviceBean adviceBean : adviceBeans) { Class<?> beanType = adviceBean.getBeanType(); if (beanType == null) { throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean); } // <2.1> 扫描有 @ModelAttribute ,无 @RequestMapping 注解的方法,添加到 modelAttributeAdviceCache 中 Set<Method> attrMethods = MethodIntrospector.selectMethods(beanType, MODEL_ATTRIBUTE_METHODS); if (!attrMethods.isEmpty()) { this.modelAttributeAdviceCache.put(adviceBean, attrMethods); } // <2.2> 扫描有 @InitBinder 注解的方法,添加到 initBinderAdviceCache 中 Set<Method> binderMethods = MethodIntrospector.selectMethods(beanType, INIT_BINDER_METHODS); if (!binderMethods.isEmpty()) { this.initBinderAdviceCache.put(adviceBean, binderMethods); } // <2.3> 如果是 RequestBodyAdvice 或 ResponseBodyAdvice 的子类,添加到 requestResponseBodyAdviceBeans 中 if (RequestBodyAdvice.class.isAssignableFrom(beanType)) { requestResponseBodyAdviceBeans.add(adviceBean); } if (ResponseBodyAdvice.class.isAssignableFrom(beanType)) { requestResponseBodyAdviceBeans.add(adviceBean); } } // <2.3> 将 requestResponseBodyAdviceBeans 添加到 this.requestResponseBodyAdvice 属性种 if (!requestResponseBodyAdviceBeans.isEmpty()) { this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans); } // 打印日志 if (logger.isDebugEnabled()) { int modelSize = this.modelAttributeAdviceCache.size(); int binderSize = this.initBinderAdviceCache.size(); int reqCount = getBodyAdviceCount(RequestBodyAdvice.class); int resCount = getBodyAdviceCount(ResponseBodyAdvice.class); if (modelSize == 0 && binderSize == 0 && reqCount == 0 && resCount == 0) { logger.debug("ControllerAdvice beans: none"); } else { logger.debug("ControllerAdvice beans: " + modelSize + " @ModelAttribute, " + binderSize + " @InitBinder, " + reqCount + " RequestBodyAdvice, " + resCount + ", ResponseBodyAdvice"); } } }
getDefaultArgumentResolvers 获得默认的 HandlerMethodArgumentResolver 数组。
getDefaultInitBinderArgumentResolvers 获得默认的 HandlerMethodArgumentResolver 数组
getDefaultReturnValueHandlers 获得默认的 HandlerMethodReturnValueHandler 数组
supportsInternal 实现 #supportsInternal() 接口,默认返回 true
1 2 3 4 @Override protected boolean supportsInternal(HandlerMethod handlerMethod) { return true; }
getLastModifiedInternal 默认返回 -1
1 2 3 4 @Override protected long getLastModifiedInternal(HttpServletRequest request, HandlerMethod handlerMethod) { return -1; }
handleInternal 处理请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { // 处理结果 ModelAndView 对象 ModelAndView mav; // <1> 校验请求 checkRequest(request); // Execute invokeHandlerMethod in synchronized block if required. // <2> 调用 HandlerMethod 方法 if (this.synchronizeOnSession) { // 同步相同 Session 的逻辑 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); } // <3> TODO WebContentGenerator if (!response.containsHeader(HEADER_CACHE_CONTROL)) { if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) { applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers); } else { prepareResponse(response); } } return mav; }
checkRequest
1 2 3 4 5 6 7 8 9 10 11 12 protected final void checkRequest(HttpServletRequest request) throws ServletException { // Check whether we should support the request method. String method = request.getMethod(); if (this.supportedMethods != null && !this.supportedMethods.contains(method)) { throw new HttpRequestMethodNotSupportedException(method, this.supportedMethods); } // Check whether a session is required. if (this.requireSession && request.getSession(false) == null) { throw new HttpSessionRequiredException("Pre-existing session required but none found"); } }
主要是 HttpMethod 的类型和是否有 Session 的校验。
synchronizeOnSession 属性,控制是否同步相同 Session 的逻辑
1 2 3 4 5 6 7 8 public static Object getSessionMutex(HttpSession session) { Assert.notNull(session, "Session must not be null"); Object mutex = session.getAttribute(SESSION_MUTEX_ATTRIBUTE); if (mutex == null) { mutex = session; } return mutex; }
因为锁是通过 synchronized 是JVM 进程级,所以在分布式环境下,无法达到同步相同 Session 的功能。默认情况下,synchronizeOnSession 为 false 。
invokeHandlerMethod 调用 HandlerMethod 方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 @Nullable protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { // <1> 创建 ServletWebRequest 对象 ServletWebRequest webRequest = new ServletWebRequest(request, response); try { // <2> 创建 WebDataBinderFactory 对象 WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod); // <3> 创建 ModelFactory 对象 ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory); // <4> 创建 ServletInvocableHandlerMethod 对象,并设置其相关属性 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); // <5> 创建 ModelAndViewContainer 对象,并初始其相关属性 ModelAndViewContainer mavContainer = new ModelAndViewContainer(); mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request)); modelFactory.initModel(webRequest, mavContainer, invocableMethod); mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect); // <6> TODO 芋艿 1003 async AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response); asyncWebRequest.setTimeout(this.asyncRequestTimeout); // <7> TODO 芋艿 1003 async WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); asyncManager.setTaskExecutor(this.taskExecutor); asyncManager.setAsyncWebRequest(asyncWebRequest); asyncManager.registerCallableInterceptors(this.callableInterceptors); asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors); // <8> TODO 芋艿 1003 async 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); } // <9> 执行调用 invocableMethod.invokeAndHandle(webRequest, mavContainer); // <10> TODO 芋艿 1003 async if (asyncManager.isConcurrentHandlingStarted()) { return null; } // <11> 获得 ModelAndView 对象 return getModelAndView(mavContainer, modelFactory, webRequest); } finally { // <12> 标记请求完成 webRequest.requestCompleted(); } }
创建 ServletWebRequest 对象。
创建 WebDataBinderFactory 对象
创建 ModelFactory 对象
创建 ServletInvocableHandlerMethod 对象,然后设置其属性。
创建 ModelAndViewContainer 对象,并初始其相关属性
invokeAndHandle
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { // <x> 执行调用 Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs); // 设置响应状态码 setResponseStatus(webRequest); // 设置 ModelAndViewContainer 为请求已处理,返回 if (returnValue == null) { // 返回 null if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) { mavContainer.setRequestHandled(true); return; } } else if (StringUtils.hasText(getResponseStatusReason())) { // 有 responseStatusReason mavContainer.setRequestHandled(true); return; } // 设置 ModelAndViewContainer 为请求未处理 mavContainer.setRequestHandled(false); Assert.state(this.returnValueHandlers != null, "No return value handlers"); // 处理器返回值 try { this.returnValueHandlers.handleReturnValue( returnValue, getReturnValueType(returnValue), mavContainer, webRequest); } catch (Exception ex) { if (logger.isTraceEnabled()) { logger.trace(formatErrorForReturnValue(returnValue), ex); } throw ex; } }
调用父类 InvocableHandlerMethod 的 invokeForRequest
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 @Nullable public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { // <y> 解析参数 Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs); if (logger.isTraceEnabled()) { logger.trace("Arguments: " + Arrays.toString(args)); } // 执行调用 return doInvoke(args); } protected Object doInvoke(Object... args) throws Exception { // <z1> 设置方法为可访问 ReflectionUtils.makeAccessible(getBridgedMethod()); try { // <z2> 执行调用 return getBridgedMethod().invoke(getBean(), args); } catch (IllegalArgumentException ex) { assertTargetBean(getBridgedMethod(), getBean(), args); String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument"); throw new IllegalStateException(formatInvokeError(text, args), ex); } catch (InvocationTargetException ex) { // Unwrap for HandlerExceptionResolvers ... Throwable targetException = ex.getTargetException(); if (targetException instanceof RuntimeException) { throw (RuntimeException) targetException; } else if (targetException instanceof Error) { throw (Error) targetException; } else if (targetException instanceof Exception) { throw (Exception) targetException; } else { throw new IllegalStateException(formatInvokeError("Invocation failure", args), targetException); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 @Nullable private ModelAndView getModelAndView(ModelAndViewContainer mavContainer, ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception { // <1> TODO 1017 ModelFactory modelFactory.updateModel(webRequest, mavContainer); // 情况一,如果 mavContainer 已处理,则返回“空”的 ModelAndView 对象。 if (mavContainer.isRequestHandled()) { return null; } // 情况二,如果 mavContainer 未处,则基于 `mavContainer` 生成 ModelAndView 对象 ModelMap model = mavContainer.getModel(); // 创建 ModelAndView 对象,并设置相关属性 ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus()); if (!mavContainer.isViewReference()) { mav.setView((View) mavContainer.getView()); } // TODO 1004 flashMapManager 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; }
如果 mavContainer 已处理,则返回“空”的 ModelAndView 对象
如果 mavContainer 未处,则基于 mavContainer 生成 ModelAndView 对象。