Spring MVC 提供多種靈活的參數綁定機制,適應不同業務場景。本文系統整理六大核心方式、適用條件、優缺點對比與最佳實務建議。
| 方式 | 註解/類型 | 適用 Content-Type | GET/POST | 優點 | 缺點 |
|---|---|---|---|---|---|
| 1. 直接映射 | 方法參數同名 | application/x-www-form-urlencoded | GET/POST* | 最簡潔 | 參數多時簽名冗長;POST 需特定 Content-Type |
| 2. HttpServletRequest | 原生 API | 所有 | GET/POST | 完全控制、無限制 | 樣板代碼多、耦合 Servlet API |
| 3. 實體 Bean (Command Object) | POJO 參數 | application/x-www-form-urlencoded multipart/form-data | GET/POST | 物件導向、自動封裝、易驗證 | 需屬性名完全匹配 |
| 4. @ModelAttribute | 標註參數 | application/x-www-form-urlencoded | POST | 明確語義、支援 Session 屬性預綁定 | POST 專用、略顯冗餘 |
| 5. @RequestParam | 標註參數綁定 | application/x-www-form-urlencoded GET: 所有 | GET/POST* | 參數名映射、必填控制、預設值 | JSON 請求體不支援 |
| 6. @RequestBody | 請求體反序列化 | application/json application/xml | POST/PUT | 複雜對象圖、REST 標準 | 需 Jackson/JAXB、GET 不適用 |
* POST 需 Content-Type: application/x-www-form-urlencoded
@GetMapping("/addUser1")
public String addUser1(String username, String password) {
// URL: /addUser1?username=abc&password=123
return "index";
}
@PostMapping("/addUser2")
public String addUser2(HttpServletRequest request) {
String username = request.getParameter("username");
String password = request.getParameter("password");
return "index";
}
@PostMapping("/addUser3")
public String addUser3(UserModel user) {
// 自動調用 setUsername/setPassword
return "index";
}
public class UserModel {
private String username;
private String password;
// getter/setter
}
@PostMapping("/addUser5")
public String addUser5(@ModelAttribute("user") UserModel user) {
// 等同方式 3,但可配合 @SessionAttributes 實現表單向導
return "index";
}
@GetMapping("/addUser6")
public String addUser6(
@RequestParam("username") String username,
@RequestParam(value = "password", required = false, defaultValue = "123456") String password
) {
// 必填檢查、重命名、預設值
return "index";
}
@PostMapping("/addUser7")
public String addUser7(@RequestBody UserModel user) {
// 請求體: {"username":"abc","password":"123"}
// 需配置 HttpMessageConverter (Jackson)
return "index";
}
@PostMapping("/user")
public ResponseEntity> createUser(@Valid @RequestBody UserDTO dto, BindingResult result) {
if (result.hasErrors()) {
return ResponseEntity.badRequest().body(result.getAllErrors());
}
return ResponseEntity.ok(userService.create(dto));
}
// 綁定所有參數到 Map
@GetMapping("/search")
public String search(@RequestParam Map params) { ... }
// 綁定同名多值參數
@GetMapping("/filter")
public String filter(@RequestParam("tags") List tags) { ... }
| Content-Type | 支援方式 | 不支援方式 |
|---|---|---|
| application/x-www-form-urlencoded | 1,2,3,4,5 | 6 |
| multipart/form-data (檔案上傳) | 2,3 | 1,4,5,6 |
| application/json | 2,6 | 1,3,4,5 |
| application/xml | 2,6 | 1,3,4,5 |
@Valid 驗證@RequestPart 區分檔案與元數據HttpServletRequest(方式 2),除非需要訪問 Header/Cookie/Session 等原生資訊Spring MVC 的參數綁定機制極其靈活,核心原理是 HandlerMethodArgumentResolver 鏈。理解各方式的適用邊界與 Content-Type 依賴關係,能讓 Controller 代碼既簡潔又健壯,是 Spring 開發者的必修內功。