SpringMVC 表單標簽庫(spring:form)提供了服務端模型與 HTML 表單的雙向綁定能力。本文通過一個用戶註冊完整示例,涵蓋實體建模、控制器處理、JSP 表單渲染、日期格式化、枚舉綁定、集合綁定、結果回顯全流程,代碼可直接落地項目。
src/
├─ main/
│ ├─ java/
│ │ └─ cn/zifangsky/
│ │ ├─ controller/UserController.java
│ │ ├─ model/User.java, Gender.java
│ └─ webapp/
├─ WEB-INF/
│ ├─ pages/userForm.jsp, userResult.jsp
│ └─ springmvc-servlet.xml
└─ index.jsp
springmvc
org.springframework.web.servlet.DispatcherServlet
1
springmvc
*.html
encodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
UTF-8
encodingFilter
/*
package cn.zifangsky.model;
public enum Gender {
MALE, FEMALE
}
package cn.zifangsky.model;
import java.time.LocalDate;
import org.springframework.format.annotation.DateTimeFormat;
public class User {
private String name;
private String password;
private String job;
@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate birthDate;
private Gender gender;
private String country;
private boolean smoking;
// 全部 getter/setter 省略
}
關鍵點:@DateTimeFormat 配合 mvc:annotation-driven 自動註冊 FormattingConversionService,實現字符串↔LocalDate 雙向轉換,無需自定義 PropertyEditor。
package cn.zifangsky.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import cn.zifangsky.model.Gender;
import cn.zifangsky.model.User;
@Controller
public class UserController {
private static final String[] COUNTRIES = {"China", "Japan", "North Korea", "United States"};
// 1. 顯示表單:GET /form.html
@RequestMapping(value = "/form.html", method = RequestMethod.GET)
public ModelAndView showForm() {
ModelAndView mav = new ModelAndView("userForm");
mav.addObject("user", new User()); // 命令對象
mav.addObject("genders", Gender.values()); // 枚舉數組
mav.addObject("countries", COUNTRIES); // 字符串數組
return mav;
}
// 2. 處理提交:POST /result.html
@RequestMapping(value = "/result.html", method = RequestMethod.POST)
public ModelAndView submit(@ModelAttribute("user") User user) {
ModelAndView mav = new ModelAndView("userResult");
mav.addObject("u", user); // 回顯
return mav;
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java"%>
<%@ taglib prefix="form" uri="https://www.springframework.org/tags/form"%>
用戶註冊
用戶註冊
姓名:
密碼:
職業:
生日:
(格式: yyyy-MM-dd)
性別:
國家:
吸煙:
| HTML 標簽 | Spring Form 標簽 | 適用類型 |
|---|---|---|
<input type="text"> | <form:input path="..."/> | String、數字、日期 |
<input type="password"> | <form:password path="..."/> | 密碼 |
<textarea> | <form:textarea path="..."/> | 長文本 |
<input type="radio"> | <form:radiobuttons path="..." items="${...}"/> | 枚舉、List、Map、數組 |
<select><option> | <form:select path="..." items="${...}"> | 下拉選單 |
<input type="checkbox"> | <form:checkbox path="..."/> | Boolean、集合元素 |
<%@ page contentType="text/html;charset=UTF-8" language="java"%>
註冊結果
註冊成功
姓名 ${u.name}
密碼 ${u.password}
職業 ${u.job}
生日 ${u.birthDate}
性別 ${u.gender}
國家 ${u.country}
吸煙 ${u.smoking}
重新填寫
https://localhost:8080/項目名/ → 自動重定向到 form.html → 顯示表單。User 對象 → 轉發 userResult.jsp 回顯所有字段。在 User 字段添加註解:
@NotBlank(message = "姓名不能為空")
@Size(max = 20, message = "姓名長度不超過20")
private String name;
@NotBlank @Size(min = 6, max = 20)
private String password;
@Past(message = "生日必須是過去日期")
private LocalDate birthDate;
控制器方法簽名改為:
public ModelAndView submit(@Valid @ModelAttribute("user") User user, BindingResult result) {
if (result.hasErrors()) {
return new ModelAndView("userForm"); // 回顯錯誤
}
return new ModelAndView("userResult").addObject("u", user);
}
JSP 中 自動顯示錯誤信息。
| 現象 | 原因 | 解決 |
|---|---|---|
| 日期綁定失敗 | 缺少 @DateTimeFormat 或 mvc:annotation-driven | 補全註解與配置,或註冊 Formatter |
| 枚舉單選框不勾選 | items="${genders}" 傳入錯誤 | 確保傳入 Gender.values() 或 List |
| 下拉框無法回顯 | path 對應字段類型與 items 元素類型不匹配 | 字段為 String 時 items 應為 String[]/List |
| 複選框綁定 List | Boolean 單值 vs 集合 | 多選用 form:checkboxes path="hobbies" items="${allHobbies}"/>,字段為 List |
| 表單重複提交 | 無防重機制 | 引入 @SessionAttributes + SessionStatus 或 Token 機制 |
SpringMVC 表單處理核心要素:
@ModelAttribute("user") User 自動實例化並綁定請求參數。mav.addObject("user", new User()) 讓 GET 請求顯示空表單。path 對應字段名,items 提供選項集合。@DateTimeFormat + mvc:annotation-driven 解決日期雙向轉換。@Valid + BindingResult + form:errors 完成服務端校驗閉環。掌握此套流程,可高效構建類後台管理、用戶中心等大量表單交互場景。