[原創]SpringMVC中@ModelAttribute用法小結

 

 

[原創]SpringMVC中@ModelAttribute用法小結

顧名思義,@ModelAttribute註釋可以爲模型添加屬性。@ModelAttribute通常是和@RequestMapping配合使用的,@ModelAttribute和@RequestMapping註釋位置有所不同,其用法也有區別。

1. ModelAttribute和RequestMapping分開註釋不同方法

先來一張項目結構圖,User類是POJO類,MyController實現對請求的處理,index.jsp是登陸頁面,result.jsp是處理結果頁面:

User類如下:

package matest;

public class User {
	private String loginname;
	private String password;

	public User() {
		super();
	}

	public User(String loginname, String password) {
		this.loginname = loginname;
		this.password = password;
	}

	public String getLoginname() {
		return loginname;
	}

	public void setLoginname(String loginname) {
		this.loginname = loginname;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	@Override
	public String toString() {
		return this.getLoginname() + this.getPassword();
	}
}

result.jsp用來顯示MyController的處理結果:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
你好${user.loginname}<br>

</body>
</html>

下面先看MyController類中,只有@RequestMapping存在的情況:

@Controller
public class MyController {
	@RequestMapping("/login")
	public String skrWu() {
		return "result";
	}
}

當向後端發送/login請求時,將會尋找被@ReuqestMapping標記的方法,進行匹配。這種情況下,會直接返回result.jsp視圖。

登錄結果:

可以看到,因爲我們沒有進行任何處理,所以沒有打印user的loginname信息,這是理所當然的。

現在,輪到@ModelAttribute登場了,我們爲MyController添加一個用@ModelAttribute註釋的test()方法,來接收前端傳來的登錄名和密碼信息,生成和保存User對象。

@Controller
public class MyController {
	@ModelAttribute
	public User test(@RequestParam("loginname") String loginname, @RequestParam("password") String password) {
		User user = new User();
		user.setLoginname(loginname);
		user.setPassword(password);
		return user;
	}

	@RequestMapping("/login")
	public String skrWu() {
		return "result";
	}
}

再次運行,

運行結果:

這次就有user的loginname信息了。原因何在呢?

原來,在執行被@RequestMapping標註的方法前,SpringMVC會先依次執行被@ModelAttribute標註的方法。在這個例子裏,先運行的test() 方法接收了前端傳來的登錄名和密碼信息,並將其值傳給了新建的user對象。在test() 方法執行結束後,user對象已經存儲在了model當中。之後運行skrWu() 方法,跳轉到result.jsp,因此可以在result.jsp中訪問user對象了。如果test() 方法沒有被@ModelAttribute標註,是無法得到運行的。

在這種默認寫法(@ModelAttribute)下,model中user的屬性名就是test()方法的返回類型User的小寫。如果想要自定義模型中user的屬性名,可以採用@ModelAttribute("屬性名");或者model.addAttribute("屬性名", 屬性值);兩種方法。如下:

​
    @ModelAttribute("userWu")
	public User test(@RequestParam("loginname") String loginname, @RequestParam("password") String password,Model model) {
		User user = new User();
		user.setLoginname(loginname);
		user.setPassword(password);
		return user;
	}

​

或者

@ModelAttribute
	public void test(@RequestParam("loginname") String loginname, @RequestParam("password") String password,Model model) {
		User user = new User();
		user.setLoginname(loginname);
		user.setPassword(password);
		model.addAttribute("userWu", user);
	}

這樣,在result.jsp中就可以通過${userWu.loginname}訪問登錄名了。

2.@ModelAttribute出現在@RequestMapping註釋的方法的參數裏

改寫MyController類如下:

@Controller
public class MyController {

	@RequestMapping("/login")
	public String skrWu(@ModelAttribute("user1") User user) {
		return "result";
	}
}

改寫result.jsp如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
你好${user1.loginname}<br>
${user1.password}<br>
</body>
</html>

通過前端頁面或者URL發送請求:

或:

結果如下:

可見參數已經傳給了user1對象。

那麼總結一下,當[@ModelAttribute("屬性名") 類型 對象 ]出現在方法參數中時,它首先會試圖自動將form表單或URL裏的屬性傳給對象,這時甚至不用顯式使用set方法,只要欲傳遞的屬性名(loginname,password)在POJO類和前端表單name中對應即可。

3.@ModelAttribute和@RequestMapping同時註釋同一個方法

輪到freeStyle出場了。

新建MyControllerV2類:

@Controller
public class MyControllerV2 {
	@ModelAttribute("user")
	@RequestMapping("/freeStyle")
	public String skrWu() {
        //freeStyle:將要跳轉的視圖名
        //user(屬性名)=result(屬性值) 
		return "result";
	}
}

前端對應/freeStyle請求的代碼塊片段爲

<a href="freeStyle" >
    <button>點我跳轉到freeStyle!</button>
</a>

新建freeStyle.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
${user}
</body>
</html>

點擊下圖按鈕,

結果爲:

下面分析一下執行過程:

 當@ModelAttribute和@RequestMapping同時註釋skrWu()方法時,此時方法的返回值不再代表視圖名,取而代之的是@RequestMapping的value值成爲了視圖名。而@ModelAttribute的value值代表屬性名,方法返回值此時代表ModelAttribute屬性名的屬性值。和前面兩種情況區別較大。

4.@ModelAttribute出現在@RequestMapping修飾的方法的返回值之前

可能很多人已經暈了,寫成代碼大概是這個樣子:

@RequestMapping("/請求")

public @ModelAttribute("屬性名") 返回值 方法名(參數名){方法體}

至於這樣寫的作用,還是看例子吧。

重寫MyControllerV2類,如下:

@Controller
public class MyControllerV2 {
	@RequestMapping("/freeStyle")
	public @ModelAttribute("wuli") User test(@RequestParam("loginname") String loginname,
			@RequestParam("password") String password) {
		User user = new User();
		user.setLoginname(loginname);
		user.setPassword(password);
		return user;
	}
}

前端/freeStyle請求對應的代碼塊如下:

<form action="freeStyle" method="post">
<table>
<tr>
<td><label>登錄名:</label></td>
<td><input type="text" id="logins" name="loginname" ></td>
</tr>
<tr>
<td><label>密碼:</label></td>
<td><input type="text" id="password" name="password" ></td>
</tr>
<tr>
 <td><input type="submit" id="submit" value="登錄" ></td>
</tr>
</table>
</form>

freeStyle.jsp如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
你好,${wuli.loginname}
</body>
</html>

登錄。。

登錄結果:

分析:@RequestMapping的行爲和第3種情況類似,方法返回值不再代表視圖名(畢竟類型也不同了),取而代之的是@RequestMapping的value值代表了視圖名,在這個例子裏爲freeStyle.jsp。@ModelAttribute("屬性名")會把方法返回值存入model,相當於執行了 model.setAttribute("wuli",user);

不過值得注意的是,這種情況下,SpringMVC並不會試圖自動將前端傳入的參數賦給@ModelAttribute修飾的對象,需要手動賦值。因此,如果註釋掉

//user.setLoginname(loginname);
//user.setPassword(password);

就無法獲得對象wuli的屬性值了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章