ModelAndViewContainer主要是用来返回Model对象的,在ModelAndViewContainer中有defaultModel和redirectModel,

defaultModel是默认使用的Model,后者用于传递redirect时的参数,我们在处理中使用了Model或ModelMap时,ArgumentResolver会传入defaultModel,它是BindingAwareModelMap类型,既继承了ModelMap又实现了Model接口,所以在处理器中使用Model或者ModelMap其实使用的是同一个对象,Map参数传入的也是这个对象。处理器中RedirectAttributes类型的参数ArgumentResolver会传入redirectModel,它实际上是RedirectAttributeModelMap类型。

ModelAndViewContainer中其实就是一个ModelMap,一系列的操作都是基于ModelMap的。

public class ModelAndViewContainer {

	private boolean ignoreDefaultModelOnRedirect = false;

	//视图,可以是实际视图也可以是String类型的逻辑视图
	private Object view;

	//默认使用的Model
	private final ModelMap defaultModel = new BindingAwareModelMap();

	//redirect类型的Model
	private ModelMap redirectModel;

	private boolean redirectModelScenario = false;

	//用于设置SessionAttribute使用完的标志
	private final SessionStatus sessionStatus = new SimpleSessionStatus();

	//请求是否已经处理完成的标志
	private boolean requestHandled = false;

	public void setIgnoreDefaultModelOnRedirect(boolean ignoreDefaultModelOnRedirect) {
		this.ignoreDefaultModelOnRedirect = ignoreDefaultModelOnRedirect;
	}

	//设置视图名称
	public void setViewName(String viewName) {
		this.view = viewName;
	}

	public String getViewName() {
		return (this.view instanceof String ? (String) this.view : null);
	}

	public void setView(Object view) {
		this.view = view;
	}

	public Object getView() {
		return this.view;
	}

	public boolean isViewReference() {
		return (this.view instanceof String);
	}

	public ModelMap getModel() {
		if (useDefaultModel()) {
			return this.defaultModel;
		}
		else {
			return (this.redirectModel != null) ? this.redirectModel : new ModelMap();
		}
	}

	//和model相关的处理方法
     /*
       * 假设redirectModelScenario = R ,ignoreDefaultModelOnRedirect = I ,(redirectModel == null)= M
       * 那么(R, I, M)共有8中组合情况,useDefaultModel返回false(也就是使用redirectModel)只有三种情况:
       * (1,1,0)、(1,1,1)、(1,0,0)
       * a:如果同时设置了redirectModelScenario和ignoreDefaultModelOnRedirect为true,那么无论redirectModel
       *    是否为null,都会使用redirectModel;
       * b:如果设置了redirectModelScenario为true,而ignoreDefaultModelOnRedirect为false,同时redirectModel
       *    为null,那么也会使用redirectModel;
	*/
	private boolean useDefaultModel() {
		return (!this.redirectModelScenario || (this.redirectModel == null && !this.ignoreDefaultModelOnRedirect));
	}

	public ModelMap getDefaultModel() {
		return this.defaultModel;
	}

	public void setRedirectModel(ModelMap redirectModel) {
		this.redirectModel = redirectModel;
	}

	public void setRedirectModelScenario(boolean redirectModelScenario) {
		this.redirectModelScenario = redirectModelScenario;
	}

	public SessionStatus getSessionStatus() {
		return this.sessionStatus;
	}

	public void setRequestHandled(boolean requestHandled) {
		this.requestHandled = requestHandled;
	}

	public boolean isRequestHandled() {
		return this.requestHandled;
	}

	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;
	}

	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;
	}

	public boolean containsAttribute(String name) {
		return getModel().containsAttribute(name);
	}

}

ModelMap其实就是一个HashMap而已,主要用于数据的存取而已。

@SuppressWarnings("serial")
public class ModelMap extends LinkedHashMap<String, Object> {

	public ModelMap() {
	}

	public ModelMap(String attributeName, Object attributeValue) {
		addAttribute(attributeName, attributeValue);
	}

	public ModelMap(Object attributeValue) {
		addAttribute(attributeValue);
	}

	public ModelMap addAttribute(String attributeName, Object attributeValue) {
		Assert.notNull(attributeName, "Model attribute name must not be null");
		put(attributeName, attributeValue);
		return this;
	}

	public ModelMap addAttribute(Object attributeValue) {
		Assert.notNull(attributeValue, "Model object must not be null");
		if (attributeValue instanceof Collection && ((Collection<?>) attributeValue).isEmpty()) {
			return this;
		}
		return addAttribute(Conventions.getVariableName(attributeValue), attributeValue);
	}

	public ModelMap addAllAttributes(Collection<?> attributeValues) {
		if (attributeValues != null) {
			for (Object attributeValue : attributeValues) {
				addAttribute(attributeValue);
			}
		}
		return this;
	}

	public ModelMap addAllAttributes(Map<String, ?> attributes) {
		if (attributes != null) {
			putAll(attributes);
		}
		return this;
	}

	public ModelMap mergeAttributes(Map<String, ?> attributes) {
		if (attributes != null) {
			for (Map.Entry<String, ?> entry : attributes.entrySet()) {
				String key = entry.getKey();
				if (!containsKey(key)) {
					put(key, entry.getValue());
				}
			}
		}
		return this;
	}

	public boolean containsAttribute(String attributeName) {
		return containsKey(attributeName);
	}

}

springMVC源码分析--ModelAndViewContainer和ModelMap的更多相关文章

  1. 8、SpringMVC源码分析(3):分析ModelAndView的形成过程

    首先,我们还是从DispatcherServlet.doDispatch(HttpServletRequest request, HttpServletResponse response) throw ...

  2. 7、SpringMVC源码分析(2):分析HandlerAdapter.handle方法,了解handler方法的调用细节以及@ModelAttribute注解

    从上一篇 SpringMVC源码分析(1) 中我们了解到在DispatcherServlet.doDispatch方法中会通过 mv = ha.handle(processedRequest, res ...

  3. 框架-springmvc源码分析(一)

    框架-springmvc源码分析(一) 参考: http://www.cnblogs.com/heavenyes/p/3905844.html#a1 https://www.cnblogs.com/B ...

  4. springMVC源码分析--ViewNameMethodReturnValueHandler返回值处理器(三)

    之前两篇博客springMVC源码分析--HandlerMethodReturnValueHandler返回值解析器(一)和springMVC源码分析--HandlerMethodReturnValu ...

  5. springMVC源码分析--HandlerMethodReturnValueHandlerComposite返回值解析器集合(二)

    在上一篇博客springMVC源码分析--HandlerMethodReturnValueHandler返回值解析器(一)我们介绍了返回值解析器HandlerMethodReturnValueHand ...

  6. springMVC源码分析--RequestParamMethodArgumentResolver参数解析器(三)

    之前两篇博客springMVC源码分析--HandlerMethodArgumentResolver参数解析器(一)和springMVC源码解析--HandlerMethodArgumentResol ...

  7. springMVC源码分析--访问请求执行ServletInvocableHandlerMethod和InvocableHandlerMethod

    在之前一篇博客中springMVC源码分析--RequestMappingHandlerAdapter(五)我们已经简单的介绍到具体请求访问的执行某个Controller中的方法是在RequestMa ...

  8. springMVC源码分析--页面跳转RedirectView(三)

    之前两篇博客springMVC源码分析--视图View(一)和springMVC源码分析--视图AbstractView和InternalResourceView(二)中我们已经简单的介绍了View相 ...

  9. springMVC源码分析--HttpMessageConverter写write操作(三)

    上一篇博客springMVC源码分析--HttpMessageConverter参数read操作中我们已经简单介绍了参数值转换的read操作,接下来我们介绍一下返回值的处理操作.同样返回值的操作操作也 ...

随机推荐

  1. ps图层的基本使用

    图层的使用 图层的基本使用一:复制,选择多个,背景图上添加图片,同时移动多个图层 复制图层:图层里的内容位置会变化,而拷贝的图层,图层里的位置不变,跟原来的图层一样 选择多个图层:shift选中多个图 ...

  2. Http协议消息报头

    哎.不知道怎么写Http协议... 超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议. HTTP基于TCP/IP通信协议来传递数据 ...

  3. 【机器学习】Iris Data Set(鸢尾属植物数据集)

    注:数据是机器学习模型的原材料,当下机器学习的热潮离不开大数据的支撑.在机器学习领域,有大量的公开数据集可以使用,从几百个样本到几十万个样本的数据集都有.有些数据集被用来教学,有些被当做机器学习模型性 ...

  4. MongoDB 分片集群搭建

    一.概述 分片是一种在多台机器上分配数据的方法.MongoDB使用分片来支持具有非常大的数据集和高吞吐量操作.有两种解决系统增长的方法:垂直扩展和水平扩展. 垂直扩展涉及增加单个服务器的容量,例如使用 ...

  5. 众说纷纭的ul、ol、li

    (1)提到ul ol li,大家都知道,就是三个列表标签,ul表示无需列表(unordered list),ol表示有序列表(oredr list), li 表示列表项(list item),之前我也 ...

  6. Java 中的时间日期 API

    自从 14 年发布 Java 8 以后,我们古老 java.util.Date 终于不再是我们 Java 里操作日期时间的唯一的选择. 其实 Java 里的日期时间的相关 API 一直为世猿诟病,不仅 ...

  7. 直接插入排序算法:ArrayList实现和数组实现

    直接插入排序算法思想: 排序区间R[1..n]: 在排序的过程中,整个排序区间被分为两个子区间: 有序区R[ 1 ... i-1 ]和无序区R[ i ... n ]: 共进行n-1趟排序,每趟排序都是 ...

  8. [ZJOI 2010]Perm 排列计数

    Description 题库链接 询问有多少个 \(1\sim N\) 的排列 \(P\) 满足" \(\forall i\in[2,N], P_i>P_{\frac{i}{2}}\) ...

  9. [Luogu 3768]简单的数学题

    Description 输入一个整数n和一个整数p,你需要求出$(\sum_{i=1}^n\sum_{j=1}^n ijgcd(i,j))~mod~p$,其中gcd(a,b)表示a与b的最大公约数. ...

  10. [HNOI2004]树的计数

    题目描述 输入输出格式 输入格式: 输入文件第一行是一个正整数n,表示树有n个结点.第二行有n个数,第i个数表示di,即树的第i个结点的度数.其中1<=n<=150,输入数据保证满足条件的 ...