ModelAndViewContainer component analysis

The ModelAndViewContainer is responsible for transferring the data throughout the request process, storing the Model and View, and other functionsCopy the code

Variables in ModelAndViewContain

/ / if it is true, the processor back to redirect the rabbit is must not use defaultModel private Boolean ignoreDefaultModelOnRedirect = false; // View, physical View of type Object,View or logical View of type String Private Final ModelMap defaultModel = new BindingAwareModelMap(); // Redirect private ModelMap redirectModel; Private Boolean redirectModelScenario = false; /* Names of attributes with binding disabled */ private final Set<String> bindingDisabledAttributes = new HashSet<String>(4); private HttpStatus status; Private final SessionStatus SessionStatus = new SimpleSessionStatus(); Private Boolean requestHandled = false;Copy the code

DefaultModel and redirectModel:

The ModelAndViewContain contains two models: DefaultModel and redirectModel defaultModel is the Model used by default and redirectModel is the Model used to redirect When a Model or ModelMap is used in the processor,ArgumentResolve passes in the defaultModel. The defaultModel is of type BindingAwareModelMap, which implements the Model interface So using Model or ModelMap in the processor actually uses the same object, and the Map argument is passed in as an argument of type RedirectAttributes in the object handler. ArgumentResolve is passed in as redirectModel RedirectModel actually RedirectAttributesModelMap typeCopy the code

ModelAndViewContain#getMode

The ModelAndViewContain#getMode method returns one of these two models depending on the criteria

public ModelMap getModel() { if (useDefaultModel()) { return this.defaultModel; } else { if (this.redirectModel == null) { this.redirectModel = new ModelMap(); } return this.redirectModel; } } private boolean useDefaultModel() { return (! this.redirectModelScenario || (this.redirectModel == null && ! this.ignoreDefaultModelOnRedirect)); }Copy the code
UseDefaultModel method logic: If redirectModelScenario is false and the redirect view is not returned, defaultModel is returned. If redirectModelScenario is true and the Redirect view is returned, RedirectModel is not null, or return to redirectModel ignoreDefaultModelOnRedirect = true IgnoreDefaultModelOnRedirect RequestMappingHandlerAdapter Settings RedirectModelScenario is a flag returned by the processor to indicate whether it is a Redirect view, set in ReturnValueHandler, ReturnValueHandler sets redirectModelScenario to true if it determines that it is a Redirect view A ReturnValueHandler must contain a defaultModel before it contains a ReturnValueHandlerCopy the code

Understand the logic of the getModel, go back to see RequestMappingHandlerAdapter# getModelAndView getModel

private ModelAndView getModelAndView(ModelAndViewContainer mavContainer, ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception { modelFactory.updateModel(webRequest, mavContainer); if (mavContainer.isRequestHandled()) { return null; } ModelMap model = mavContainer.getModel(); ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus()); if (! mavContainer.isViewReference()) { mav.setView((View) mavContainer.getView()); } if (model instanceof RedirectAttributes) { Map<String, ? > flashAttributes = ((RedirectAttributes) model).getFlashAttributes(); HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes); } return mav; }Copy the code
When getModel returns the redirectModel, the parameters that the processor sets to the Model are not used (except with SessionAttribute set). Only the Redirect returns the redirectModel, which does not require rendering the page. When getModel returns defaultModel, the parameters set to RedirectAttributes are discarded. Therefore, if the View returned is not of type Redircet, Even if the processor sets the parameters using RedirectAttributes, they are not passed to the next request. The parameters passed via @sessionattribute are set in ModelFactory#updateModel Using mavContainer getDefaultModel method, is used to ensure any case defaultModel so, only set the parameters to the Model or the ModelMap sessionAttribute cache, The parameters set to RedirectAttributes are not availableCopy the code
Public void updateModel(NativeWebRequest Request, ModelAndViewContainer Container) throws Exception {// Take defaultModel, // Set to Model or ModelMap to use the sessionAttribute cache // Set to RedirectAttributes parameters cannot ModelMap defaultModel = container.getDefaultModel(); if (container.getSessionStatus().isComplete()){ this.sessionAttributesHandler.cleanupAttributes(request); } else { this.sessionAttributesHandler.storeAttributes(request, defaultModel); } if (! container.isRequestHandled() && container.getModel() == defaultModel) { updateBindingResult(request, defaultModel); }}Copy the code

Attribute operation

ModelAndViewContainer provides methods to add, merge, and delete properties that call Model operations directly

Public ModelAndViewContainer addAttribute(String name, Object value) {getModel().addattribute (name, value); return this; Public ModelAndViewContainer addAttribute(Object value) {getModel().adDattribute (value); return this; } public ModelAndViewContainer addAllAttributes(Map<String,? > attributes) { getModel().addAllAttributes(attributes); return this; } // Merge: Public ModelAndViewContainer mergeAttributes(Map<String,? > attributes) { getModel().mergeAttributes(attributes); return this; } public ModelAndViewContainer removeAttributes(Map<String,? > attributes) { if (attributes ! = null) { for (String key : attributes.keySet()) { getModel().remove(key); } } return this; }Copy the code

SessionStatus properties

SessionStatus properties

SessionStatus is the SessionStatus parameter used by the handler to notify the completion of the SessionAttribute use and to indicate whether the SessionAttribute is used up If you run out, clear the SessionAttribute parameter in the ModelFactory#updateModel method otherwise set the current Model parameterCopy the code

RequestHandler properties

RequestHandler properties

It is used to indicate whether the request has been completely processed. If the request has been processed, the response has been returned RequestHandler is set to true if the handler returns an @responseBody annotation or an HttpEntity typeCopy the code