07-ModeAndView和View
文章目录ModeAndView一、ModeAndView和DispatcherServlet二、代码2.1 关键属性2.2 构造方法2.3 读取方法2.4 赋值方法2.5 ModelMap三、ViewModeAndView一、ModeAndView和DispatcherServletModeAndView 是DispatcherServlet中请求处理器执行后的返回结果(HandlerAd...
·
文章目录
ModeAndView
一、ModeAndView和DispatcherServlet
- ModeAndView 是DispatcherServlet中请求处理器执行后的返回结果(HandlerAdapter 执行后的返回结果),在SpringMvc中ModeAndView是一个比较简单的类,没有继承关系,代码也比较少。
- 下面是源码中对该类的注释
/**
* 在MVC框架中同时持有Model和View,但是他们是相互独立的,这个类的目的仅仅是
* 为了让Handler处理器能够在一起响应返回中同时返回MOdel和View
*
* Holder for both Model and View in the web MVC framework.
* Note that these are entirely distinct. This class merely holds
* both to make it possible for a controller to return both model
* and view in a single return value.
*
* ModelAndView代表了一个请求处理器的返回, 由 DispatcherServlet 解析,
* View 可以有一个名字,通过视图解析器 ViewResolver 来处理,也可以由一
* 个名字来唯一确定,Model 是一个Map集合,可以使用多个键值对。
*
* <p>Represents a model and view returned by a handler, to be resolved
* by a DispatcherServlet. The view can take the form of a String
* view name which will need to be resolved by a ViewResolver object;
* alternatively a View object can be specified directly. The model
* is a Map, allowing the use of multiple objects keyed by name.
*/
-
从前面的注释大概知道视图和 Model 是什么,Model 本质就是数据,可以理解为处理后返回的数据,比如键值对,View 由一个名字来标识,需要视图解析器来解析。
-
DispatcherServlet中关键代码如下关键代码如下:
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
//省略...
ModelAndView mv = null;
mappedHandler = getHandler(processedRequest);
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
//调用Handler处理器,返回 ModeAndView
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
//省略...
}
二、代码
2.1 关键属性
public class ModelAndView {
//View实例或者View的字符串名称
@Nullable
private Object view;
//Model的Map集合
@Nullable
private ModelMap model;
//响应的HTTP status选项
@Nullable
private HttpStatus status;
//标记是否被clear方法清空
private boolean cleared = false;
2.2 构造方法
- ModeAndView提供了很多重载的构造方法,都比较简单,提供了不同的构造参数,列出典型的如下:
public ModelAndView(String viewName, @Nullable Map<String, ?> model) {
this.view = viewName;
//将model属性添加到Mode对应的Map集合中
if (model != null) {
getModelMap().addAllAttributes(model);
}
}
2.3 读取方法
- 读取方法主要是获取内部的 View 或者 Model,status 等属性,很多 setXX 方法;
public String getViewName() {
return (this.view instanceof String ? (String) this.view : null);
}
protected Map<String, Object> getModelInternal() {
return this.model;
}
public ModelMap getModelMap() {
if (this.model == null) {
this.model = new ModelMap();
}
return this.model;
}
2.4 赋值方法
- 赋值方法主要是给属性赋值,也比较简单,都是 setXX 方法;
public void setViewName(@Nullable String viewName) {
this.view = viewName;
}
public void setStatus(@Nullable HttpStatus status) {
this.status = status;
}
//添加模型值
public ModelAndView addObject(String attributeName, @Nullable Object attributeValue) {
getModelMap().addAttribute(attributeName, attributeValue);
return this;
}
//清空
public void clear() {
this.view = null;
this.model = null;
this.cleared = true;
}
- ModeAndView 本身比较简单,内部持有一个 View 对象和其名称,还有一个 Model 对象,Model 本质是一个包含了属性的 Map 集合,提供了相关的读写方法,添加 Model 属性的方法等,后面我们看看保存 Model 属性的这个 ModelMap。
2.5 ModelMap
- ModelMap 用于保存 Model 的属性,也比较简单,提供了很多属性的读写方法;
/**
* 实现Map接口用于构建模型数据,支持链式调用和根据名称构建Model
*
* Implementation of {@link java.util.Map} for use when building model data for use
* with UI tools. Supports chained calls and generation of model attribute names.
*
* 这个类充当MVC的通用模型但是并不绑定。
*
* <p>This class serves as generic model holder for Servlet MVC but is not tied to it.
* Check out the {@link Model} interface for an interface variant.
*/
@SuppressWarnings("serial")
public class ModelMap extends LinkedHashMap<String, Object> {
//构造方法
public ModelMap(Object attributeValue) {
addAttribute(attributeValue);
}
//添加键值对属性
public ModelMap addAttribute(String attributeName, @Nullable 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(@Nullable Map<String, ?> attributes) {
if (attributes != null) {
putAll(attributes);
}
return this;
}
//属性合并
public ModelMap mergeAttributes(@Nullable Map<String, ?> attributes) {
if (attributes != null) {
attributes.forEach((key, value) -> {
if (!containsKey(key)) {
put(key, value);
}
});
}
return this;
}
//判断是否包含属性
public boolean containsAttribute(String attributeName) {
return containsKey(attributeName);
}
}
三、View
-
View 代表 MVC 的视图,在 SpringMvc 中 View 是一个接口,其子类负责渲染内容并且呈现模型(数据)
-
单个示图可以包含很多模型(数据);View的实现有很多种,典型的是JSP,其他实现比如 XSLT-based、Xml、html甚至Excel格式,定义接口的目的是避免限制可能的实现方式。
-
示图是一个Bean,可以通过示图解析器ViewResolver来实例化,而且 View 是没有状态的,因此实现类是线程安全的。
-
下面是View接口的源码,本身比较简单,省去了部分属性,只有两个方法;
public interface View {
//返回示图的内容,可以在渲染之前检查示图的内容
@Nullable
default String getContentType() {
return null;
}
//按照指定的模型渲染视图,模式本质就是数据
//第一步是准备请求,比如在 JSP 中就是设置模型数据为响应的属性
//第二步就是渲染视图,比如通过 RequestDispatcher 填充 JSP
void render(@Nullable Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception;
}
- 后面文章再看看 View 接口的具体实现类,重点看看 MappingJackson2JsonView 实现类,并自定义实现一种 View 视图方式;
更多推荐
已为社区贡献2条内容
所有评论(0)