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的請求參數的獲取、傳遞,模型傳遞,都十分靈活。