0058 Spring MVC如何向視圖傳值--Model--ModelMap--ModelAndView--@ModelAttribute


MVC,模型、視圖、控制器,請求來了,控制器負責找到Controller進行一通計算,計算的結果放到模型里,再找視圖把結果呈現出來。

請求里一般都包含了一些參數,前面說了,Spring MVC有很多種方式可以拿到這些參數,一通計算之后把結果存到了模型里,但是這模型有哪些,怎樣順順利利的交給視圖呢?

HttpServletRequest

這個類簡直神通廣大,接受參數靠它,傳遞結果還靠他。當然了,估計后面的Model、ModelAndView都是把它封裝在其中的

ModelAndView

一接觸Spring MVC,肯定先接觸的是這個類。該類將視圖和模型放在一起,視圖名稱解析器和視圖解析器就到這個類的對象里拿數據,一開始就用它,不說了。

Model與ModelMap、Map

還是用前面的上傳書籍信息的例子,

index.html

<!DOCTYPE html>
<html>
<head>
    <title>Spring MVC如何接受瀏覽器傳遞來的參數</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
    <form action="addbook" method="POST">
        <fieldset>
            <legend>要上傳的參數</legend>
             書名:<input name="bookname" /><br>
            作者:<input name="author" /><br>
            出版社:<input name="press" /><br>
            ISBN:<input name="isbn" /><br>
            豆瓣評分:<input name="douban" /><br>
        <input type="submit" value="提交" />
        </fieldset>
        
    </form>
</body>
</html>

result.jsp

<%@page pageEncoding="utf-8" 
        contentType="text/html;charset=utf-8" %>
<html>
    <head>
        <title>返回結果</title>
    </head>
    <body style="color:blue;font-size:18px">
        您輸入的書籍信息為:<br>
        書籍的名稱:${book.bookname }<br><br>
        書籍的作者:${book.author }<br><br>
        書籍的出版社:${book.press }<br><br>
        書籍的ISBN:${book.isbn }<br><br>
        書籍的豆瓣評分:${book.douban }<br><br>
    </body>
</html> 

實體類Book省略

寫Controller

package net.sonng.mvcdemo.controller;

import net.sonng.mvcdemo.entity.Book;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class ModelDemoController {
    @RequestMapping("/addbook")
    public String modelTest(Book book,Model model){  //將Model放在形參當中
        model.addAttribute("book", book);
        return "result";
    }
}

瀏覽器訪問index.html,輸入信息后,來到result.jsp頁面,正常輸出
看起來modelTest()方法中壓根就沒有model的對象,下面調用addAttribute()方法,豈不是要拋NullPointerException異常了。其實Spring MVC在調用這個處理方法之前就已經創建了一個隱含的模型對象,如果處理方法的參數有Model或者ModelMap,那就將這個隱含對象直接傳遞過去,當然就想咋用就咋用了。

說了Model,還有ModelMap、Map呢,將上面處理方法的Model換成ModelMap或者Map,其余代碼不變。

上面把Model或者ModelMap放在形參里面是可以的,那放在局部變量里呢?
Model:這是個接口,找到一個實現類ExtendedModelMap,也是可以的
ModelMap:也可以
Map:也是個接口,用HashMap也是可以的。
所以:這個隱含對象到底是哪個類的對象?

@ModelAttribute注解----用@ModelAttribute(value="")注釋返回值為對象的方法

這個注解用法有點多,很靈活,從獲取請求參數到處理這些數據再到向視圖傳遞數據,一條線從頭到尾。
特別注意:被@ModelAttribute修飾的方法會在該控制器里的其他方法執行前執行,並且每個處理方法執行時都會執行一次
還是以傳遞書籍信息作例子

package net.sonng.mvcdemo.controller;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import net.sonng.mvcdemo.entity.Book;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class ModelAttributeDemoController {
    
    //加在方法上,該方法返回值是一個對象,相當於以“book”為key,以方法的返回值為value,添加到了model中
    //如果沒有指定key,那么默認的key是返回值類型的首字母小寫
    @ModelAttribute("book")  
    public Book getBookInfo(Book book){  //注意這里的參數封裝,跟處理方法的參數一樣:形參同名;實體類;@RequestParam
        System.out.println("getBookInfo方法執行。。。。。");  //該方法會在調用addbook()方法前先調用
        return book;
    }
    
    @RequestMapping("/addbook")
    public String addbook(){
        System.out.println("addbook方法開始執行。。。。。");
        return "result";
    }
}

視圖result.jsp如下:

<%@page pageEncoding="utf-8" 
        contentType="text/html;charset=utf-8" %>
<html>
    <head>
        <title>返回結果</title>
    </head>
    <body style="color:blue;font-size:18px">
        您輸入的書籍信息為:<br>
        書籍的名稱:${book.bookname }<br><br>  <!-- @ModelAttribute可以將一個對象傳遞過來 -->
        書籍的作者:${book.author }<br><br>
        書籍的出版社:${book.press }<br><br>
        書籍的ISBN:${book.isbn }<br><br>
        書籍的豆瓣評分:${book.douban }<br><br>
    </body>
</html> 

@ModelAttribute注解----用@ModelAttribute(value="")注釋處理方法的形參--在處理方法中獲取到綁定的對象

看代碼:

package net.sonng.mvcdemo.controller;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import net.sonng.mvcdemo.entity.Book;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class ModelAttributeDemoController {
    
    @ModelAttribute("book")
    public Book getBookInfo(Book book){
        System.out.println("getBookInfo方法執行。。。。。");
        return book;
    }
    
    @RequestMapping("/addbook")
    public String addbook(@ModelAttribute("book") Book b){  //該注解注釋形參,將getBookInfo綁定的對象賦值給形參b
        b.setBookname("書的名字被改了"); //獲取到綁定的對象后,就可以做些修改,然后傳遞給視圖
        System.out.println("addbook方法開始執行。。。。。");
        return "result";
    }
}

上面的處理方法換成這樣,也是可以獲得綁定對象的的:

    @RequestMapping("/addbook")
    public String addbook(Model model){
        Book b=(Book)model.asMap().get("book");
        b.setBookname("書的名字被改了");
        System.out.println("addbook方法開始執行。。。。。");
        return "result";
    }

@ModelAttribute注解----用@ModelAttribute注釋返回值為void的方法

看controller代碼:

package net.sonng.mvcdemo.controller;

import net.sonng.mvcdemo.entity.Book;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class ModelAttributeDemoController {
    
    @ModelAttribute  //修飾返回值為void的方法,因為沒有返回值,因而不能綁定返回值。在形參中加上Model,在視圖中就可以拿到綁定的數據
    public void getBookInfo(Book book,Model model){
        System.out.println("getBookInfo方法執行。。。。。");
        model.addAttribute("book", book);
    }
    
    @RequestMapping("/addbook")
    public String addbook(Model model){
        Book b=(Book)model.asMap().get("book");
        b.setBookname("書的名字被改了");
        System.out.println("addbook方法開始執行。。。。。");
        return "result";
    }
}

@ModelAttribute和@RequestMapping一起修飾處理方法

這種情況下,看起來有點奇怪
Controller代碼:

package net.sonng.mvcdemo.controller;

import net.sonng.mvcdemo.entity.Book;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class ModelAttributeDemoController {
    
    @ModelAttribute("info")
    @RequestMapping("/addbook")
    public String addbook(Book book){
        book.setBookname("書的名字被改了改了");
        return "result";  //這里的result不再是視圖名,而是作為字符串返回值成為key為info的對應的value的值,視圖名是請求名,也就是addbook
    }
}

把result.jsp改名為:addbook.jsp,並加一行代碼:

<%@page pageEncoding="utf-8" 
        contentType="text/html;charset=utf-8" %>
<html>
    <head>
        <title>返回結果</title>
    </head>
    <body style="color:blue;font-size:18px">
        您輸入的書籍信息為:<br>
        書籍的名稱:${book.bookname }<br><br>
        書籍的作者:${book.author }<br><br>
        書籍的出版社:${book.press }<br><br>
        書籍的ISBN:${book.isbn }<br><br>
        書籍的豆瓣評分:${book.douban }<br><br>
   @ModelAttribute綁定的數據是:${info }           <!-- 加了一行代碼 -->
    </body>
</html> 

訪問index.jsp,輸入數據提交后,返回如下頁面:

您輸入的書籍信息為:
書籍的名稱:書的名字被改了改了   //book的信息還是被傳遞到了視圖中,並且跟@ModelAttribute("info")注解無關

書籍的作者:Craig Walls 沃爾斯

書籍的出版社:人民郵電出版社

書籍的ISBN:9787115417305

書籍的豆瓣評分:8.4

@ModelAttribute綁定的數據是:result   //result成為了綁定值,傳遞到視圖,而不是視圖名

總的來說,@ModelAttribute更像是為了將請求參數的封裝跟處理方法分離,單獨用一個方法負責參數的獲取封裝

Spring MVC的請求參數的獲取、傳遞,模型傳遞,都十分靈活。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM