Spring MVC 綁定表單數(shù)據(jù)
1. 前言
在 WEB 應(yīng)用程序中,經(jīng)常會(huì)以表單的方式提交數(shù)據(jù)。使用 Spring MVC 或其它 WEB MVC 框架開發(fā)時(shí),框架本身會(huì)提供以對(duì)象為單位自動(dòng)封裝表單中數(shù)據(jù)的功能。
本節(jié)課通過一個(gè)用戶注冊(cè)的小例子,和大家聊聊 Spring MVC 是如何優(yōu)雅的以對(duì)象的方式封裝表單中的數(shù)據(jù)。
本節(jié)課程的重點(diǎn)就是請(qǐng)你一定要跟著課程案例練習(xí)一遍。
2. 對(duì)象 / 表單
以表單的方式提交數(shù)據(jù)有一個(gè)優(yōu)點(diǎn),可以把邏輯上具有內(nèi)在聯(lián)系的多個(gè)數(shù)據(jù)同時(shí)發(fā)送給服務(wù)器。原生 Servlet 開發(fā)時(shí),服務(wù)器端的響應(yīng)組件(Servlet)中,需要開發(fā)者編寫代碼從請(qǐng)求包一個(gè)一個(gè)解析出提交過來的數(shù)據(jù)。
如果數(shù)據(jù)量不多,倒還好,如果數(shù)據(jù)量較多,一個(gè)一個(gè)解析,枯燥乏味的工作除了讓人厭煩,且會(huì)耽誤開發(fā)效率。
來!通過一個(gè)案例,體會(huì) Spring MVC 是如何一步到位解析大量數(shù)據(jù)的。
案例需求描述: 實(shí)現(xiàn)用戶注冊(cè)功能。
流程分析: 通過注冊(cè)頁面,用戶輸入個(gè)人信息。表單中的數(shù)據(jù)以 POST 的請(qǐng)求方式提交至服務(wù)器,服務(wù)器端的控制器對(duì)提交過來的數(shù)據(jù)進(jìn)行處理。
實(shí)現(xiàn)流程:
2.1 編寫頁面
編寫注冊(cè)頁面,表單的提交方法設(shè)置為 POST 。
Tips: 無論數(shù)據(jù)是以 GET 或 POST 提交,本質(zhì)沒多大區(qū)別,僅表現(xiàn)在語義上的差異性。也就是說,此處使用 GET 方式提交并不影響結(jié)果。
<form action="user/register" method="post">
用戶名:<input type="text" value="" name="userName" />
<br />
密碼:<inpu type="password" value="" name="userName" />
<br />
<input type="submit" value="注冊(cè)" name="btnRegister" />
<input type="reset" value="重置" name="btnReset" />
</form>
2.2 分析控制器中的邏輯流程
注冊(cè)頁面中提交的用戶數(shù)據(jù)最終會(huì)交給服務(wù)器端的用戶控制器完成,控制器中的處理流程應(yīng)該分 3 步走:
- 從請(qǐng)求包中解析出客戶端提交過來的注冊(cè)數(shù)據(jù);
- 處理注冊(cè)數(shù)據(jù)。核心業(yè)務(wù)邏輯就是添加數(shù)據(jù)到數(shù)據(jù)庫中;
- 根據(jù)處理結(jié)果進(jìn)行頁面跳轉(zhuǎn)。
Tips: 本節(jié)課程主要講解數(shù)據(jù)綁定,會(huì)淡化后面的兩個(gè)邏輯。
2.3 綁定數(shù)據(jù)
使用 @RequestParam 注解
Spring MVC 提供有 @RequestParam 注解,通過給定參數(shù)名,可以自動(dòng)綁定請(qǐng)求包中的同名參數(shù)的數(shù)據(jù)。
代碼如下:
@Controller
@RequestMapping("/user")
public class UserAction {
@RequestMapping("/register")
public String register(@RequestParam("userName") String userNmae,
@RequestParam("userPassword") String userPassword) {
System.out.println(userNmae);
System.out.println(userPassword);
return null;
}
}
此處,使用 @RequestParam 注解綁定請(qǐng)求包中的數(shù)據(jù),有 2 個(gè)弊端:
-
如果請(qǐng)求包中傳過來的數(shù)據(jù)較多,控制器中響應(yīng)方法的參數(shù)也會(huì)增多,代碼臃腫不好維護(hù);
-
Java 語言最大的特色是面向?qū)ο缶幊蹋?strong>OOP)。很顯然,userName 和 userPassword 都是用戶的信息,以一種拆離的方式分別注入數(shù)據(jù)沒有體現(xiàn)出 OOP 的優(yōu)點(diǎn)。
那么,有沒有一種更好的替代方案或者說有一種很 OOP 的方案呢?
以 OOP 方式綁定數(shù)據(jù)
從 OOP 的角度分析,在應(yīng)用程序中必然會(huì)存在一個(gè)描述用戶的類。
public class User {
private String userName;
private String userPassword;
//……
}
能不能直接把請(qǐng)求包中提交的數(shù)據(jù)綁定到 User 類型中?
答案是肯定的,而且實(shí)現(xiàn)起來非常簡單,只需要把控制器方法的參數(shù)修改成對(duì)象類型便可。
@RequestMapping("/register",method = RequestMethod.POST)
public String register(User user) {
System.out.println(user);
return null;
}
不需要使用額外的任何注解,就可以直接綁定表單中的數(shù)據(jù)。
為什么表單中的數(shù)據(jù)能自動(dòng)綁定到對(duì)象上?
原理很簡單,表單中數(shù)據(jù)以 key=value&key=value 的方式提交,此處的 key 實(shí)質(zhì)是表單控件的名稱。前面的注冊(cè)表單中的數(shù)據(jù)在請(qǐng)求包中的格式形式如下:
userNname=abc&userPassword=123456
如上圖所示,Spring MVC 能自動(dòng)解析這個(gè)數(shù)據(jù),然后自動(dòng)注入到對(duì)象的同名屬性中。所以一定要保證對(duì)象的屬性名與表單中提交數(shù)據(jù)時(shí)使用的參數(shù)名(key)一致。
數(shù)據(jù)解析成功后,理論上講應(yīng)該要把數(shù)據(jù)送到數(shù)據(jù)庫中,本章節(jié)暫不涉及到數(shù)據(jù)庫操作。只做業(yè)務(wù)邏輯模擬。
@RequestMapping(value="/register",method = RequestMethod.POST)
public String register(User user) {
if("abc".equals(user.getUserName()) && "123456".equals(user.getUserPassword()) ) {
return "success";
}else {
return "fail";
}
}
3. 對(duì)象級(jí)聯(lián)
OOP 代碼中經(jīng)常會(huì)出現(xiàn)類似于 A 對(duì)象引用 B 對(duì)象,B 對(duì)象引用 C 對(duì)象的現(xiàn)象。 類似于現(xiàn)實(shí)生活中的小王有一輛汽車,汽車有一把鑰匙……
如果每一個(gè)用戶都有一輛汽車,用 OOP 描述,意味著 User 類中有一個(gè)對(duì) Car 的引用類型屬性。
public class User {
private String userName;
private String userPassword;
private Car car;
//……
}
假設(shè) Car 類結(jié)構(gòu)如下:
public class Car {
private String carType;
private String carColor;
//……
}
在注冊(cè)時(shí),除了要輸入用戶信息之外,還需要指定用戶所擁有的汽車類型、顏色。那么,控制器是否能自動(dòng)綁定用戶以及汽車數(shù)據(jù)?
Tips: 為什么注冊(cè)時(shí)要輸入汽車信息,不要糾結(jié),只是一個(gè)用來說明問題的例子。
答案是肯定的。
只需要在表單頁面中添加如下代碼,控制器端不做任何修改。如此,除了能接收用戶數(shù)據(jù)外,還能接收汽車的信息。
<form action="user/register" method="post">
用戶名:<input type="text" value="" name="userName" />
<br />
密碼:<input type="password" value="" name="userPassword" /> <br />
汽車類型:<input type="text" value="" name="car.carType" /> <br />
汽車顏色:<input type="text" value="" name="car.carColor" /> <br />
<input type="submit" value="注冊(cè)" name="btnRegister" />
<input type="reset" value="重置" name="btnReset" />
</form>
也就是說,Spring MVC 支持對(duì)象級(jí)聯(lián)自動(dòng)數(shù)據(jù)綁定。
Spring MVC 支持多層級(jí)的對(duì)象級(jí)聯(lián)。
4. 小結(jié)
本節(jié)課程主要是和大家講解如何綁定表單中的數(shù)據(jù)。有 2 種方式,一是使用 @RequestParam 注解,另一個(gè)就是通過一個(gè)對(duì)象參數(shù)直接綁定數(shù)據(jù)。
Spring MVC 的自動(dòng)綁定功能非常強(qiáng)大。在使用的時(shí)候可根據(jù)自己的需要自行選擇。
當(dāng)然,以 OOP 的形式綁定數(shù)據(jù)定當(dāng)是最佳、快速的選擇。