`

158. Spring Boot 形参Map并没有添加到类似于ModelAndView中,但是却可以页面取到相应的值?

阅读更多

 

【视频&交流平台】

à SpringBoot视频

http://study.163.com/course/introduction.htm?courseId=1004329008&utm_campaign=commission&utm_source=400000000155061&utm_medium=share

à SpringCloud视频

http://study.163.com/course/introduction.htm?courseId=1004638001&utm_campaign=commission&utm_source=400000000155061&utm_medium=share

à Spring Boot源码

https://gitee.com/happyangellxq520/spring-boot

à Spring Boot交流平台

http://412887952-qq-com.iteye.com/blog/2321532

 

 

需求缘起:

       有网友留言:

感谢讲解,思路很清晰,不过有点疑惑,为什么最后结尾的时候,那个形参Map并没有添加到类似于ModelAndView中,但是页面却可以取到相应的值?

 

本节大纲:

(1)留言代码翻译
(2)问题分析
(3)Spring MVC数据模型
(4)写法延伸

 

 

       接下来看下具体的内容:

留言代码翻译:

我们在controller常写的代码是这样子的:

    @RequestMapping("/index")
    public ModelAndView index(){
       ModelAndView mv = new ModelAndView("/index");
       mv.addObject("name", "[Angel -- 守护天使]");
       return mv;
    }

 

但是在我的好多代码里,却是这样子写的:

    //http://127.0.0.1:8080/spring-boot/index2
    @RequestMapping("/index2")
    public String index2(Map<String,Object> map){
       map.put("name", "[Angel -- 守护天使]");
       return "/index";
    }

 

第一个代码使用了ModelAndView,第二个直接使用了map,那为什么第二个例子的参数name也能够在前端获取到呢,或者说为什么使用map也可以呢?这就是本篇文章要解决的问题。

 

问题分析:

我们看下ModelAndView的代码:

public class ModelAndView {
 
    /** View instance or view name String */
    private Object view;
 
    /** Model Map */
    private ModelMap model;
 
    /** Optional HTTP status for the response */
    private HttpStatus status;
 
    /** Indicates whether or not this instance has been cleared with a call to {@link #clear()} */
    private boolean cleared = false;
    //省略其它代码…
}

 

       在这里有一个属性ModelMap,这个很重要,我们在看里面的addObject,源码如下:

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

 

       所以这里添加是使用了modelMap属性进行添加的,看下ModelMap源码:

public class ModelMap extends LinkedHashMap<String, Object> {
 
    /**
     * Construct a new, empty {@code ModelMap}.
     */
    public ModelMap() {
    }
    //省略其它代码…
}

 

       可以看出ModelMap继承了LinkedHashMap,而LinkedHashMap又继承了Map,所以这里map为什么也是可以设置前端属性值的,慢慢的就清楚了。

 

Spring MVC数据模型:

SpringMVC在调用方法前会创建一个隐含的数据模型,作为模型数据的存储容器, 成为”隐含模型”。如果处理方法入参为Map或者Model类型,SpringMVC会将隐含模型的引用传递给这些入参。

       spring Web MVC 提供ModelMapModelMap让我们能去暴露渲染视图需要的模型数据。

       看如下的一段很有趣的代码:

    @RequestMapping(value = "/index3")
    public String index3(Model model, Map<String,Object> model2, ModelMap model3) {
        model.addAttribute("a", "a");
        model2.put("b", "b");
        model3.put("c", "c");
        System.out.println(model == model2);
        System.out.println(model2 == model3);
        return "index3";
     }

 

       控制台的打印是:

true
true

 

 

       虽然此处注入的是三个不同的类型(Model model, Map model2, ModelMap model3),但三者是同一个对象。

       AnnotationMethodHandlerAdapterRequestMappingHandlerAdapter将使用BindingAwareModelMap作为模型对象的实现,即此处我们的形参(Model model, Map model2, ModelMap model3)都是同一个BindingAwareModelMap实例。

       我们跟踪源代码可以发现:

BindingAwareModelMap extends ExtendedModelMap

ExtendedModelMap

ExtendedModelMap extends ModelMap implements Model

       所以到头来这些都是一个引用,就可以解释的通了。

 

ModelAndView特别说明:

       我们会发现上面并没有过多的提到这个,ModelAndView:是包含ModelMap 和视图对象的容器。正如名字暗示的一样既包含模型也包含视图,而ModelMap只是包含模型的信息。

       一旦你知道这些的话,这些涉及到的类就可以比较好的理解了。

 

写法延伸:

       从上面的讲解中,我们在controller可以有很多种写法,接着往下看:

1)写法1String写法

@RequestMapping(value = "/index4")
    public String index4() {
        return "index4";
     }

 

 

2)写法2StringMap写法

    @RequestMapping(value = "/index5")
    public String index5(Map<String,Object> map) {
       map.put("name", "Andy");
        return "index5";
     }

 

 

3)写法3StringModelMap写法

    @RequestMapping(value = "/index6")
    public String index6(ModelMap modelMap) {
       modelMap.addAttribute("name","Andy-2"); 
        return "index5";
     }

 

 

4)写法4String加接口Model写法

@RequestMapping(value = "/index7")

    public String index7(Model model) {

       model.addAttribute("name","Andy-3"); 

        return"index5";

     }

 

5)写法5String加大杂烩写法

@RequestMapping(value = "/index3")
    public String index3(Model model, Map<String,Object> model2, ModelMap model3) {
        model.addAttribute("a", "a");
        model2.put("b", "b");
        model3.put("c", "c");
        return "index3";
     }

 

 

6)写法6ModelAndView写法

    @RequestMapping("/index")
    public ModelAndView index(){
       ModelAndView mv = new ModelAndView("/index");
       mv.addObject("name", "[Angel -- 守护天使]");
       return mv;
    }

 

       好了,可能还有别的写法,就到这里吧。那么这多的写法,我们用哪一种呢?所以第一一个项目要稍微保持统一,选择一到二两种就可以了,博主比较喜欢的就是MapModelAndView这两种方式了。

 

 

 

 

 

分享到:
评论

相关推荐

    60.java形参.zip

    60.java形参.zip60.java形参.zip60.java形参.zip60.java形参.zip60.java形参.zip60.java形参.zip60.java形参.zip60.java形参.zip60.java形参.zip60.java形参.zip60.java形参.zip60.java形参.zip60.java形参.zip60....

    62.函数的形参和实参.pdf

    62.函数的形参和实参

    你必须知道的495个C语言问题(PDF)

    1.10 对于没有初始化的变量的初始值可以作怎样的假定?如果一个全 局变量初始值为“零”, 它可否作为空指针或浮点零? . . . . . . . 4 1.11 代码int f() f char a[] = "Hello, world!";g 不能编译。. . . . . . . 5...

    C什么叫实参 形参 ?怎么用?区别?

    当函数被调用时,系统会根据实参的值来为形参分配内存空间,并将实参的值复制到形参中。需要注意的是,在函数调用过程中,实参的值不会发生改变。 **示例:** ```c int f(int b) /* b 为形参 */ { return b; } ...

    架构师面试题系列之Spring MVC面试专题及答案(31题).docx

    spring 容器通过映射器去寻找业务控制器,使用适配器找到相应的业务类,在进业务类时进行数据封装,在封装前可能会涉及到类型转换,执行完业务类后使用 ModelAndView 进行视图转发,数据放在 model 中,用 map 传递...

    VB.net中ByVal ByRef 形参 实参的区别,带源代码

    在VB.NET编程中,了解`ByVal`和`ByRef`关键字以及形参(形式参数)和实参(实际参数)的区别是至关重要的。这些概念直接影响到函数或方法调用时参数值的传递方式,从而影响程序的行为。下面将详细阐述这两个关键字...

    Springboot怎么集成Thymeleaf模板引擎?

    1. 添加依赖项:在 pom.xml 文件中添加以下依赖项:&lt;dependency&gt; &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt; &lt;artifactId&gt;spring-boot-starter-thymeleaf&lt;/artifactId&gt; 2. 配置 Thymeleaf:在 application....

    由形参给定的n个实数,输出平均值

    给定程序MODI1.C中的函数fun的功能是:由形参给定的n个实数,输出平均值,并统计在平均值以上(含平均值)的实数个数。 例如,n=8时,输入:193,199,195,673,195,757,196,051,196,092,196,596,196,579...

    java ee期末复习题.docx

    15. Spring MVC 支持的返回值类型:ModelAndView 返回值类型可以添加 Model 数据,并指定视图,String 返回值类型可以携带数据并跳转视图,void 返回类型主要在异步请求时使用,它只返回数据,而不会跳转视图。...

    形参实参影响调试程序

    这是因为,指针传递和引用传递都可以改变实参的值,而值传递只能改变形参的值。 结论 形参和实参的关系非常重要。在函数调用时,实参的值或地址被传递给形参,以便在被调函数中使用。值传递、指针传递和引用传递都...

    js函数形参形参接收object变量.docx

    另一个与对象参数相关的特性是解构赋值,可以方便地从对象中提取属性值,如`function myFunc({key1, key2}) {...}`,这将自动将`obj.key1`和`obj.key2`赋值给相应的形参。 总的来说,JavaScript函数接收Object变量...

    变量、指针、引用作函数形参的比较

    函数形参是C++函数学习中一大重点,经常让初学者头疼,这里我们通过讲解两个实参值互换的例子讲解实参与形参间的关系,并比较普通变量、指针以及引用作形参时的区别,了解地址、名称以及值间的联系,体会指针、引用...

    07.处理Map等CXF无法自动转换的复合数据类型的形参和返回值

    处理Map等CXF无法自动转换的复合数据类型的形参和返回值.wmv"中,很可能是对这一主题的视频教程,你可以通过观看这个视频来进一步了解和学习实际操作的过程和技巧。在学习过程中,结合实际案例进行实践,将有助于...

    C语言实参、形参、函数调用、指针、引用、&符号实例[定义].pdf

    按指针传递时,函数将实参的地址传递给形参,并可以通过指针来修改实参的原始值。 在C语言中,&符号是取地址运算符,用于获取变量的地址。例如,&n是获取变量n的地址。在函数调用时,&符号可以用于将实参的地址传递...

    VB 变量做形参实例

    在VB(Visual Basic)编程语言中,形参(Formal Parameters)是函数或过程定义时声明的参数,用于接收调用函数或过程时传递的实际参数(Actual Parameters)。本实例将探讨如何使用VB变量作为形参,以实现更灵活的...

    spring mvc学习视频相关资料

    7. **Model对象**:用于在控制器和视图之间传递数据,通常在处理方法中添加属性到模型,然后在视图中进行渲染。 8. **视图解析**:通过配置`ViewResolver`,Spring MVC能根据逻辑视图名查找实际的视图资源,如JSP、...

    乐优商城项目总结1

    3. **@Bean方法形参注入**:在@Bean注解的方法中,可以直接通过方法参数来注入依赖,Spring Boot会先创建参数对应的bean,然后注入。 4. **@ConfigurationProperties**:结合配置文件,可以将配置文件中的内容映射到...

    C语言程序设计-根据整型形参m,计算如下公式的值:y=sin(m)10;例如:若m=9,则应输出:4.121185.c

    C语言程序设计-根据整型形参m,计算如下公式的值:y=sin(m)10;例如:若m=9,则应输出:4.121185.c

    将形参s所指字符串中所有的ASCII存入形参t所指字符数组中

    给定程序中,函数fun的功能是:将形参s所指字符串中所有的ASCII码值小于97的字符存入形参t所指字符数组中,形成一个新串,并统计出符合条件的字符个数作为函数值返回。、 例如,形参s所指的字符串为:Abc@1×56*,...

    C语言函数中的三类形参.pdf

    C语言函数中的三类形参 C语言函数中的三类形参是指在函数设计过程中,形参的三种类型:前提形参、改变形参和既作前提又要改变的形参。这些形参的正确定义是函数设计的必要前提。 前提形参 前提形参是函数定义时...

Global site tag (gtag.js) - Google Analytics