http://blog.csdn.net/daryl715/article/details/1645880
http://blog.csdn.net/shuwei003/article/details/7213662
上面兩篇文章文筆比較混亂,但能看出大概的過程。
個人實踐:
1、概述:主要用到以下幾個要素:一個與表單內容對應的JavaBean類,一個用來驗證這個Bean的Validator類,一個調用這個Validator的Controller類。
所以,Validator需要知道JavaBean,Controller需要知道Validator。
剩下的都是細節。
2、例子:
(1) JavaBean
public class User { private Integer userId; private Integer parentId; private String userName; private String password; private String tel; private String email; private String qq; private String webChat; private Integer groupId; private Boolean state; private Date createTime; private Date lastTime; }
getter和setter省略了。
(2)、表單jsp頁面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>添加用戶</title>
<link href="/Public/media/css/new/page.css" rel="stylesheet"
type="text/css" />
<style type="text/css">
.errormsg {
font-family: "微軟雅黑";
color: #F30;
}
</style>
</head>
<body>
<form:form action="${pageContext.request.contextPath}/userConfig/addDA" method="post" commandName="user"> <div class="formDiv"> <table width="1020" border="0"> <tr> <td align="right">用戶名:</td> <td align="left"><form:input path="userName"/><span class="errormsg"><form:errors path="userName"/></span></td> </tr> <tr> <td align="right">密碼:</td> <td align="left"><form:password path="password"/><span class="errormsg"><form:errors path="password"/></span></td> </tr> <tr> <td align="right">電話:</td> <td align="left"><form:input path="tel"/><span class="errormsg"><form:errors path="tel"/></span></td> </tr> <tr> <td align="right">郵件:</td> <td align="left"><form:input path="email"/><span class="errormsg"><form:errors path="email"/></span></td> </tr> <tr> <td align="right">QQ:</td> <td align="left"><form:input path="qq"/><span class="errormsg"><form:errors path="qq"/></span></td> </tr> <tr> <td align="right">微信:</td> <td align="left"><form:input path="webChat"/><span class="errormsg"><form:errors path="webChat"/></span></td> </tr> <tr> <td align="right">狀態:</td> <td align="left"><table width="200"> <tr> <td><label> <input type="radio" name="StatusRadioGroup" value="禁用" id="StatusRadioGroup_0" /> 禁用 </label></td> </tr> <tr> <td><label> <input type="radio" name="StatusRadioGroup" value="生效" id="StatusRadioGroup_1" /> 生效 </label></td> </tr> </table></td> </tr> <tr> <td></td> <td><input name="" type="submit" value="提交" /></td> </tr> </table> </div> </form:form>
</body>
</html>
想要詳細了解這里用到的springmvc form標簽的意思,需要先學習相應知識:http://haohaoxuexi.iteye.com/blog/1807330
關鍵點:
a、commandName屬性指定了后台Model中與表單對應的對象的名字,需要在后台modelAndView.setObject("user",user);如果不寫該屬性,默認key是"command",那在后台就要
modelAndView.setObject("command",user)。
b、<form:input和<form:errors標簽中使用path屬性指定該表單項對應的user的屬性名。
c、注意引入springmvc的form標簽<%@taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
(3)Validator代碼
package com.leslie;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
import com.leslie.User;
public class UserValidator implements Validator{ @Override public boolean supports(Class<?> clazz) { return User.class.equals(clazz); } @Override public void validate(Object obj, Errors e) { // ValidationUtils.rejectIfEmpty(e, "name", "name.empty"); // ValidationUtils.rejectIfEmpty(e, "gender", "null"); // ValidationUtils.rejectIfEmpty(e, "age", "null"); // User s = (User)obj; // if(s.getAge() < 18){ // e.rejectValue("age","young"); // }else if(s.getAge() > 50){ // //e.reject("age", "old"); // } // if(s.getName().length() < 1){ // e.reject("name", "short"); // }else if(s.getName().length() > 10){ // e.reject("name", "long"); // } ValidationUtils.rejectIfEmpty(e, "userName", null, "用戶名不能為空"); ValidationUtils.rejectIfEmpty(e, "password", null, "密碼不能為空"); } }
關鍵點:
a、supports方法中指定了對哪個類進行驗證。
b、ValidationUtils是springmvc的工具類,你可以方便地使用它進行常用的判斷,你也可以直接使用e.rejectValue定義你自己的判斷信息,
注釋掉的語句列出了常用的用法。
c、rejectIfEmpty方法第三個參數是國際化properties文件中的key值,由於我沒有使用國際化,此處使用了第四個參數,也就是默認值。
(4) Controller實現
@Controller
@RequestMapping("/userConfig")
public class SJUserConfigController {
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.setValidator(new UserValidator());
}
@RequestMapping("/openAddUser")
public ModelAndView openAddUser() {
ModelAndView mv = new ModelAndView();
User u = new User();
mv.addObject("user",u);
mv.setViewName("addUser");
return mv;
}
@RequestMapping("/addUser")
public ModelAndView addUser(@Valid @ModelAttribute User user, BindingResult br,
HttpServletRequest requset) {
ModelAndView mv = new ModelAndView();
mv.addObject("user", user);
if (br.hasErrors()) {
mv.setViewName("addUser");
} else {
mv.setViewName("success");
}
return mv;
}
}
關鍵點:
a、@InitBinder指定了Validator。
b、注意openAddUser這個方法,這個方法執行以后首次打開表單頁供用戶填寫信息,mv.addObject("user",u);這句非常必要,u不能為null,否則jsp報錯。
c、addUser方法處理表單提交上來的內容,@Valid指定了要對其修飾的對象進行驗證,如果沒有這個注解,springmvc就不會對表單進行驗證。
3、后記
使用了上述的驗證機制以后,雖然經過測試,可以正常驗證表單,但后台服務器報
javax.validation.ValidationException: Unable to create a Configuration, because no Bean Validation provider could be found.
加入hibernate-validator.jar(以及其依賴的jboss-logging.jar和classmate.jar)以后就正常了,具體Jar的版本號此處略去。
4、后記的后記:一個巨大的坑和巨大的潛規則--commandName與@ModelAttribute必須配合默契否則不報錯但就是不顯示錯誤信息
什么意思呢?說明如下。
在前面的例子中,我很巧合地將頁面的commandName值賦為"user",而我的表單對應Java類剛好也是叫User,而且我直接這樣@ModelAttribute使用了注解,並沒有指定@ModelAttribute("xxxx"),結果
一切順利,但這只是一種巧合情況。
好,那下面我總結一下我實驗出的最后結論:
1、如果你直接使用@ModelAttribute,並沒有指定其value,那對不起,你頁面中的commandName的值必須是你的表單對應類的類名的小寫!最惡心的是,如果你不知道這一點,
隨意地給commandName起名字的話,validator會正確驗證表單,controller會正確跳轉,一切都正常,就是頁面中不顯示錯誤信息!而且不報任何錯誤!
2、如果你這樣使用@ModelAttribute注解,比如@ModelAttribute("abcdef"),那么你頁面中的commandName也必須等於"abcdef",二者匹配起來用,這樣,你才可能達到自己給commandName
起名字的目的!
后記的后記二:
如果一個controller中的方法處理兩個及兩個以上的form表單,比如,方法A()接收並處理用戶注冊信息,而方法B()接收並處理定單查詢條件,由於controller只能綁定一個validator,沒有與validator匹配的那個
表單在被提交之后也會被validator驗證並報錯,即使你沒加@Valid也會。目前沒有解決的辦法,只能將這種情況拆開兩個controller處理。