SpringMVC中ModelAndView对象与“视图解析器”

摘要: spring MVC这个环境中,Spring MVC会依据controller(或者你叫它handler)中处理方法的返回值,进行解析,解析之后提供一个视图,作为响应。 标注了@Controller的处理器,实际上本质是一个POJO,你标注了@Controller,我就高看你一眼。

spring MVC这个环境中,Spring MVC会依据controller(或者你叫它handler)中处理方法的返回值,进行解析,解析之后提供一个视图,作为响应。
标注了@Controller的处理器,实际上本质是一个POJO,你标注了@Controller,我就高看你一眼。但你的形态就是一个java代码文件。
你作为一个java的土土的文件,你里面处理方法的返回值,也就是return语句,返回了一个东西。这个东西可以是String 也可以是 ModelAndView对象。这就是标注了@Controller的方法的全部工作。

接下来,Spring容器(或者说Spring MVC容器)需要接着你抛来的返回值,不管你的返回值是String还是ModelAndView,我,作为一个容器,我全都封装成ModelAndView对象。然后,我,Spring容器的一部分,视图解析器,开始工作。

视图解析器的英文名字叫做 ViewResolver,这个东西首先是Spring定义得人一个接口,具体你的Spring容器中的视图解析器有怎样的功能,取决于你为你自己的Spring容器配置了哪种具体的Spring视图解析器的实现类。

看看之前我们看过的一个图:
这个是spring mvc 的jar中的默认配置

当然你的spring项目也可以在配置文件中覆盖上述配置(我并没有用别的视图解析器取代默认的InternalResourceViewResolver):

/**
     * @return 登录验证
     */
    @RequestMapping("/dologin")
    public ModelAndView dologin(HttpServletRequest request, User user) {

        User us1 = uss.getUserByName(user.getSrName());
        ModelAndView mav = new ModelAndView();
        mav.setViewName("forward:/login.jsp");
        if (us1 == null) {
            mav.addObject("errorMsg", "用户名不存在");
        } else if (!us1.getSrPwd().equals(user.getSrPwd())) {
            mav.addObject("errorMsg", "用户密码不正确");
        } else {

        } 

        return mav;
    }

@Controller中的方法返回值最终都是ModelAndView,我们需要搞清楚两件事:
1.ModelAndView是什么?
2.视图解析器究竟做了哪些工作,才能返回我们需要的视图?

我们应该先看看ModelAndView是怎么回事:
ModelAndView是Spring中标准的类,完全是Spring自己封装的对象。Spring API中如此描述这个对象:
public class ModelAndView extends java.lang.Object

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.

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.

用人话解释一下ModelAndView是干什么用的,ModelAndView包含两部分:一个View和一个Model
View由setViewName()方法来决定,决定让ViewResolver去哪里找View文件,并找到是哪个jsp文件;
Model由addObject()方法来决定,它的本质是java的HashMap,键值对;
用人话来解释ModelAndView的功能就是,View负责渲染Model,让你找到代表View的jsp,用这个jsp去渲染Model中的数据。

看看Spring源码:
Spring官网提供的API

去这个路径找一下:

也就是说ModelAndView对象中的核心成员就是Object和ModelMap
其中ModelMap也是Spring自己定义的对象。

ModelMap的本质是Java的标准容器:LinkedHashMap
属性成员我们已经搞清楚了,下面是方法成员:
setViewName()方法和addObject()方法

   public void setViewName(@Nullable String viewName)
  {
    this.view = viewName;
  }

  public ModelAndView addObject(String attributeName, Object attributeValue)
  {
    getModelMap().addAttribute(attributeName, attributeValue);
    return this;
  }

  public ModelAndView addObject(Object attributeValue)
  {
    getModelMap().addAttribute(attributeValue);
    return this;
  }

  public ModelMap getModelMap()
  {
    if (this.model == null) {
      this.model = new ModelMap();
    }
    return this.model;
  }

也就是说,ModelAndView对象没有什么神秘之处,解构一下核心就是Object\LinkedHashMap,完全是Java的标准容器(对象)。
也就是说,关键不在于ModelAndView对象,而在于“视图解析器”这个Spring容器的核心部件。

那么视图解析器怎样工作呢?
你明明知道你用的ViewResolver的实现类就是InternalResourceViewResolver,那么你应该仔细看看Spring API中这一部分的详细内容:
https://docs.spring.io/spring/docs/5.0.1.RELEASE/javadoc-api/

首先InternalResourceViewResolver extends(继承)了 UrlBasedViewResolver;
然后顺便说,把用于显示(view)的jsp文件放在WEB-INF文件夹下是一种安全的做法,这样不能通过url直接access这些jsp,只能通过Controller java类来访问它们。

于是我们继续去看UrlBasedViewResolver

我想这样一个Spring官方的API中的说明性文字已经足以解开所有疑惑:那就是ModelAndView对象的方法setViewName()中的参数,看上去像是一个普通字符串的参数,究竟应该采用哪种格式?应该怎么写?已经有了定论。

As a special feature, redirect URLs can be specified via the "redirect:" prefix. E.g.: "redirect:myAction.do" will trigger a redirect to the given URL, rather than resolution as standard view name. This is typically used for redirecting to a controller URL after finishing a form workflow.

Furthermore, forward URLs can be specified via the "forward:" prefix. E.g.: "forward:myAction.do" will trigger a forward to the given URL, rather than resolution as standard view name. This is typically used for controller URLs; it is not supposed to be used for JSP URLs - use logical view names there

时间: 2024-11-07 18:05:31

SpringMVC中ModelAndView对象与“视图解析器”的相关文章

springmvc中设置多个视图解析器

最近一直用的是Springboot +vue 前后端分离的 架构 ,所以对于Springmvc的各种配置有些生疏,看了下多个视图解析器的东西,觉得挺好的,所以想记下来 freemark 和jsp的视图解析器的配置 1 <!--===============通用视图解析器 begin===============--> 2 <bean id="viewResolverCommon" 3 class="org.springframework.web.servle

SpringMVC系列(七)视图解析器和视图

在springmvc.xml里面配置视图解析器 1 <!-- 配置视图解析器: 如何把 handler 方法返回值解析为实际的物理视图 --> 2 <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 3 <property name="prefix" value="/WEB-INF/views/">&l

SpringMVC源码阅读:视图解析器

1.前言 SpringMVC是目前J2EE平台的主流Web框架,不熟悉的园友可以看SpringMVC源码阅读入门,它交代了SpringMVC的基础知识和源码阅读的技巧 本文将通过源码(基于Spring4.3.7)分析,弄清楚SpringMVC如何完成视图解析的 2.源码分析 在SpringMVC源码阅读:拦截器分析过doDispatch的运行过程,这里再分析一遍 回到DispatcherServlet类的doDispatch方法,看看doDispatch如何获取ModelAndView Hand

SSM-SpringMVC-10:SpringMVC中PropertiesMethodNameResolver属性方法名称解析器

------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 上次的以继承MultiActionController可以实现一个处理器中多个处理方法,但是局限出来了,他们的url访问地址只能是与方法名称相同的,因为他默认的方法名称解析器是InternalPathMethodNameResolver 如果我们想为了程序的安全甚至更多考虑(从url简洁啊,同名啊,等等)所以引入了一个叫PropertiesMethodNameResolver属性方法名称解析器的这个东西 我

SSM-SpringMVC-11:SpringMVC中ParameterMethodNameResolver参数方法名称解析器

------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 或许曾经的我们也见过一种方式http://localhost:8080/项目名/后台servlet?actionName=login&uname=admin&upwd=123 这种方式调度servlet并且传参数,这里我要表达什么呢?就是?后面可以拼接内容, 所以,此处的ParameterMethodNameResolver就是通过这种方式来访问到的方法名的 说一下案例使用步骤 一,定义Paramet

7.SpringMVC 配置式开发-ModelAndView和视图解析器

ModelAndView 1.Model(模型) 1.model的本质就是HashMap,向模型中添加数据,就是往HashMap中去添加数据 2.HashMap 是一个单向查找数组,单向链表数组 3.LinkedHashMap,本质是一个HashMap,但其将Entry进行了扩展,变成双向的了 2.View(视图) ModelAndView 内部通过 setViewName() 指定视图名称 这个视图名称对应一个视图对象,这个视图对象会被封装在ModelAndView中,传给视图解析器来解析 视

SpringMVC -- @ModelAttribute/视图,视图解析器/国际化

@ModelAttribute 这个注解注释比较多.. 我自己都有点看懵逼了... 还是在原来的例子上的Demo.... @ModelAttribute 和视图解析,以及国际化 我都写一起了,就不分开了.. package com.springmvc.handlers; import com.springmvc.model.User; import com.springmvc.model.User2; import org.springframework.stereotype.Controlle

SpringMVC——视图和视图解析器

请求处理方法执行完成后,最终返回一个 ModelAndView对象.对于那些返回 String,View 或 ModeMap 等类型的处理方法,Spring MVC 也会在内部将它们装配成一个ModelAndView 对象,它包含了逻辑名和模型对象的视图 Spring MVC 借助视图解析器(ViewResolver)得到最终的视图对象(View),最终的视图可以是 JSP ,也可能是Excel.JFreeChart 等各种表现形式的视图 对于最终究竟采取何种视图对象对模型数据进行渲染,处理器并

SpringMvc:视图和视图解析器

请求处理方法执行完成后,最终返回一个ModelAndView对象,对于返回String,View或ModelMap等类型的处理方法,SpringMvc也会在内部将它们装配成一个ModelAndView对象的,它包含了逻辑名和模型对象的视图. SpringMvc借助视图解析器(ViewResolver)得到最终的视图对象(View),最终的视图可能是JSP,也可能是Excel等各种表现形式的视图.对于最终采取何种视图对象对模型数据进行渲染,处理器并不关心,处理器的工作重点聚焦在生产模型数据的工作上