SpringMVC Model ModelAndView ModelMap Map

个人理解:View为服务器上的某个文件容器,可以为JSP,FTL等动态页面文件,甚至是媒体文件等等,单单是一个文件。Model的作用是存储动态页面属性,动态页面文件即View可以在Model中获取动态数据,这样就实现了View和Model分离的目的。接下来分别对这三个做一下说明。

一、首先是View:View接口在org.springframework.web.servlet.View包内。核心方法:

  1、getContentType()获取当前view的ContentType(),同http请求中的ContenType()是一样的作用。

  2、render(Map model, HttpServletRequest request, HttpServletResponse response)。

  render(使成为;递交;给予;表达;渲染)Dispatcher(发报机; 收发; 调度;调度员 )

  根据参数就可以知道,这个是为视图绑定Request,Response和Model的方法。

  3、View的一个实现类AbstractView,其中有方法:

复制代码
(s&g)BeanName(String beanName)

  (s&g)ContentType(String contentType)

  (s&g)RequestContextAttribute(String requestContextAttribute)

  setAttributesCSV(String propString)

  setAttributes(java.util.Properties attributes)

  (s&g)AttributesMap(Map attributes) 

  addStaticAttribute(String name, Object value)

  Map getStaticAttributes()

  (s&i)ExposePathVariables(boolean exposePathVariables)

  Map createMergedOutputModel(Map model, HttpServletRequest request,HttpServletResponse response)

  RequestContext createRequestContext(HttpServletRequest request, HttpServletResponse response, Map model)

  renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response)

  exposeModelAsRequestAttributes(Map model, HttpServletRequest request)

  writeToResponse(HttpServletResponse response, ByteArrayOutputStream baos)
  setResponseContentType(HttpServletRequest request, HttpServletResponse response)
复制代码

  其中后面的是与组合Model和Response的方法。

  根据源码可知,View其中的staticAttributes其实最终还是给了Model,通过mergedModel.putAll(pathVars);

  4、view的子接口SmartView,唯一一个方法isRedirectView,用于标记是否是重定向View。

  RedirectView实现SmartView接口,继承AbstractUrlBasedView,AbstractUrlBasedView又继承自AbstractView,就是一个基本的Url的View,内部方法:

  包含一个url属性,标记重定向到哪个url,还有一系列和http相关的协议参数,如encodingScheme,statusCode,contextRelative等等,以及其他实现View中的方法。

 二、model,model相对简单,就是一些属性的键值对而已。merge(融合,整合)

  1、方法有:

  Model addAttribute(String attributeName, Object attributeValue);  

  Model addAttribute(Object attributeValue);

  Model addAllAttributes(Collection attributeValues);

  Model addAllAttributes(Map attributes);

  Model mergeAttributes(Map attributes);

  boolean containsAttribute(String attributeName);

  Map asMap();

  其中只加值的时候,属性名通过org.springframework.core.Conventions的getVariableName生成。

  该接口的实现类为ExtendedModelMap,特殊的,ExtendedModelMap继承了ModelMap类,而ModelMap其实是继承了LinkedHashMap类。

  ExtendedModelMap的所有方法,都在ModelMap中实现了。

  2、Model有个子接口RedirectAttributes,用于设置重定向的属性。比Model里面多了一个Model,RedirectAttributes中其实是有两个Map的。

  RedirectAttributes addFlashAttribute(String attributeName, Object attributeValue);

  RedirectAttributes addFlashAttribute(Object attributeValue);

  Map getFlashAttributes();

  他的实现类为RedirectAttributesModelMap,同样继承自ModelMap,内部成员有DataBinder数据用于数据绑定,flashAttributes则是另一个Map,保存着重定向的属性。

  该类构造时直接传入一个数据绑定器,可为null,RedirectAttributesModelMap(org.springframework.validation.DataBinderdataBinder)

  转发与重定向区别可参考(http://www.cnblogs.com/shenliang123/archive/2011/10/27/2226892.html)

三、ModelAndView,顾名思义,就是整合了Model和View,常用于动态页面也是,一个后台网页就包含这两部分,前台就是基本的html代码。

  内部包含一个Object类型的view,一个ModelMap类型的model,还有一个标记是否被clear()方法清除的cleared变量。

  构造方法:ModelAndView()

  ModelAndView(String viewName)

  ModelAndView(View view)

  ModelAndView(String viewName, Map model)

  ModelAndView(View view, Map model)

  ModelAndView(String viewName, String modelName, Object modelObject)

  ModelAndView(View view, String modelName, Object modelObject)

  (s&g)ViewName

  (s&g)View

  boolean hasView

  isReference:如果view instanceof String则为true

  Map getModelInternal()

  ModelMap getModelMap()

  Map getModel() 

  ModelAndView addObject(String attributeName, Object attributeValue)

  ModelAndView addObject(Object attributeValue)

  ModelAndView addAllObjects(Map modelMap)

  void clear():清除其中的view和model

  由此可以看出,构造View可以直接使用字符串,相当于路径引用View

 四、最后,这几个实际中到底是在哪使用,如何使用的呢?

  Spring架构中,他是使用在@Controller层中的@RequestMapping注解方法中的,该注解方法有以下几种:

  返回值可以有:ModelAndView, Model, ModelMap, Map,View, String, void

  参数可以任意多,参数可以为POJO对象,可以为PO,可以为Array,List,String等等,只要能和Request中参数名一致,Spring就会自动绑定到特定的数据类型中,非常方便。其中有三个特殊类型的参数:HttpServletRequest request, HttpServletResponse response, Model model,其中第一个为当前网页发过来的请求,第二个是要返回的形影,第三个则是当前网页发过来的model参数集以及要设置给返回视图的参数集Model。

  注:参数中的Model也可以变为同样的Map,或者ModelMap,三者等价。

  来看看不同类型的返回值代表什么吧。

  1、ModelAndView

复制代码
@RequestMapping("/show1") 
public ModelAndView show1(HttpServletRequest request, 
           HttpServletResponse response) throws Exception { 
       ModelAndView mav = new ModelAndView("/demo2/show"); 
       mav.addObject("account", "account -1"); 
       return mav; 
   } 
复制代码

  这种是直接把View和Model封装好返回给Spring,Spring再交给动态网页架构去返回静态html给客户端。

  通过ModelAndView构造方法可以指定返回的页面名称,也可以通过setViewName()方法跳转到指定的页面 ,使用addObject()设置需要返回的值,addObject()有几个不同参数的方法,可以默认和指定返回对象的名字。
  2、Model=ModelMap=Map,是一样的

复制代码
@RequestMapping("/demo2/show") 
    public Map getMap() { 
        Map map = new HashMap(); 
        map.put("key1", "value-1"); 
        map.put("key2", "value-2"); 
        return map; 
    } 
复制代码

  相当于把Map返回给当前网页。在jsp页面中可直通过${key1}获得到值, map.put()相当于request.setAttribute方法。key值包括 - . 时会有问题.

  3、View 可以返回pdf excel等各种View,此时该View的Model可以在方法传递的参数中设置。只需在方法中加上参数Model model,对该model设置属性,都会反馈到该View中。

  4、String,其实也是View,该View是urlView,指定返回的视图页面名称,结合设置的返回地址路径加上页面名称后缀即可访问到。

@RequestMapping(value = "/something", method = RequestMethod.GET) 
@ResponseBody 
public String helloWorld()  { 
return "Hello World"; 
} 

  注意:如果方法声明了注解@ResponseBody ,则会直接将返回值输出到页面。上面的结果会将文本"Hello World "直接写到http响应流。

  若没有注解@ResponseBody,则对应的逻辑视图名为“center”,URL= prefix前缀+视图名称 +suffix后缀组成。如果以绝对路径书写,则在applicationContext路径为根的目录下寻找View。

@RequestMapping("/welcome") 
public String welcomeHandler() { 
  return "center"; 
} 

  5.最后一个特殊的为void,响应的视图页面对应为访问地址。

@RequestMapping("/welcome") 
public void welcomeHandler() {} 

  此例对应的逻辑视图名为"welcome"。

  PS:1.使用 String 作为请求处理方法的返回值类型是比较通用的方法,这样返回的逻辑视图名不会和请求 URL 绑定,具有很大的灵活性,而模型数据又可以通过 ModelMap 控制。
  2.使用void,map,Model 时,返回对应的逻辑视图名称真实url为:prefix前缀+视图名称 +suffix后缀组成。
  3.使用String,ModelAndView返回视图名称可以不受请求的url绑定,ModelAndView可以设置返回的视图名称。

  补充:

  Model model,HttpServletRequest request, ModelMap map声明变量,都可以赋属性和属性值,具体先引用谁呢?

    request.getSession().setAttribute("test", "haiwei2Session");
    request.setAttribute("test", "haiwei1request"); 
    map.addAttribute("test", "haiweiModelMap");
    model.addAttribute("test", "haiweiModel");

  通过${test}取值,优先取Model和ModelMap的,Model和ModelMap是同一个东西,谁最后赋值的就取谁的,然后是request,最后是从session中获取。

  更多内容参考:http://www.360doc.com/content/14/0309/19/834950_359081989.shtml



你可能感兴趣的:(Spring,MVC)