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