Web 應用中表單提交流程:顯示表單 → 用戶填寫提交 → 服務端綁定/驗證 → 成功轉成功頁、失敗回表單頁顯示錯誤。Spring MVC SimpleFormController 將此流程封裝為模板方法,開發者只需擴展關鍵點。
public class UserRegisterController extends SimpleFormController {
private BbtForum bbtForum;
public UserRegisterController() { setCommandClass(User.class); }
protected void doSubmitAction(Object command) throws Exception {
User user = (User) command;
bbtForum.registerUser(user);
}
}
protected ModelAndView onSubmit(Object command, BindException errors) throws Exception {
User user = (User) command;
bbtForum.registerUser(user);
return new ModelAndView(getSuccessView(), "user", user); // 邏輯視圖名來自 successView 屬性
}
優先級:onSubmit() > doSubmitAction(),二者只會執行一個。
<bean name="/registerUser.html" class="com.baobaotao.web.user.UserRegisterController">
<property name="bbtForum" ref="bbtForum"/>
<property name="formView" value="register"/> <!-- 表單頁 -->
<property name="successView" value="registerSuccess"/> <!-- 成功頁 -->
</bean>
配合 InternalResourceViewResolver(prefix=/WEB-INF/jsp/, suffix=.jsp)解析為具體 JSP。
<%@ taglib prefix="form" uri="https://www.springframework.org/tags/form" %>
<form:form> <!-- 無需 action,自動提交到當前控制器 -->
用戶名:<form:input path="userName"/> <font color="red"><form:errors path="userName"/></font><br/>
密碼:<form:password path="password"/> <font color="red"><form:errors path="password"/></font><br/>
Email:<form:input path="email"/> <font color="red"><form:errors path="email"/></font><br/>
<input type="submit" value="註冊"/>
</form:form>
formBackingObject() 創建命令對象(可覆寫從 DB 加載編輯數據)initBinder() 註冊自定義屬性編輯器(非基本類型必需)bindOnNewForm 決定是否將 GET 參數綁定到命令對象(默認 false)onBindOnNewForm() 綁定後回調referenceData() 準備下拉框等參考數據(返回 ModelMap)formView 顯示表單sessionForm 判斷是否從 Session 取命令對象(默認 false)onBind() 綁定後、驗證前回調validateOnBinding 觸發 Validator 驗證,錯誤收集到 ErrorsonBindAndValidate() 驗證後回調(適合業務規則驗證,如用戶名唯一性)processFormSubmission() 內部處理提交formView;無錯誤 → 繼續isFormChangeRequest() 判斷是否表單變更請求(默認 false)onSubmit() 或 doSubmitAction() → 返回 successViewprotected Object formBackingObject(HttpServletRequest request) throws Exception {
int userId = ServletRequestUtils.getIntParameter(request, "userId", -1);
return bbtForum.getUser(userId);
}
protected void onBindAndValidate(HttpServletRequest request, Object command, BindException errors) {
User user = (User) command;
if (bbtForum.isExsitUserName(user.getUserName())) {
errors.rejectValue("userName", "exists.userName", "用戶名已存在");
}
}
public class UserValidator implements Validator {
private static final Pattern EMAIL_PATTERN = Pattern.compile("\\w+@\\w+\\.\\w{2,3}");
public boolean supports(Class clazz) { return User.class.equals(clazz); }
public void validate(Object target, Errors errors) {
User u = (User) target;
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "userName", "required.username", "用戶名必填");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password", "required.password", "密碼必填");
if (!EMAIL_PATTERN.matcher(u.getEmail()).matches())
errors.rejectValue("email", "invalid.email", "Email格式錯誤");
}
}
配置 ResourceBundleMessageSource (bean name="messageSource") 指定 basenames=errors,提供 errors.properties、errors_zh_CN.properties 實現錯誤消息國際化。