參考資料:http://www.mkyong.com/spring-mvc/spring-mvc-form-errors-tag-example/css
<%Enumeration<String> enums=request.getAttributeNames();
while(enums.hasMoreElements()){
String key=enums.nextElement();
if(key.equals("org.springframework.validation.BindingResult.改成本身spring表單名")){
BeanPropertyBindingResult valuess=(BeanPropertyBindingResult)request.getAttribute(key);
out.print("=========######===========<br/>");
for(FieldError or:valuess.getFieldErrors()){
out.print(or.getCode()+"<br/>");
out.print("------------------------<br/>");
//out.print(or.getDefaultMessage()+"<br/>");
for(String codes:or.getCodes()){
out.print(codes+"<br/>");
}
// out.print(or.getArguments()+"<br/>");
out.print(or.getField()+"<br/>");
out.print(or.getRejectedValue()+"<br/>");
out.print("====================<br/>");
}
out.print("====================<br/>");
}
}
}
%>html
最近作的一個項目使用了 Spring MVC3, 其中驗證也是使用Spring的 validate 框架, 但不是所有。java
咱們 只是使用了org.springframework.validation.Errors, org.springframework.validation.BindingResult 來將驗證錯誤信息返回到JSP頁面。由於Spring提供了<form:errors>標籤來顯示BindingResult對象裏的錯誤信 息, 而且這個驗證框架還支持國際化, errorCode對應的語言文字放到工程的message資源文件就行了。spring
下面是一個簡單的註冊帳戶的例子:包括三個文件:JSP, AccountValidator和AccountValidator。數據庫
1. 首先是JSP頁面:addAccount,jsp的表單api
<form:form modelAttribute="accountVo" action="${actionUrl}" method="post">
<form:hidden path="id" readonly=「readonly」/>瀏覽器
<form:input path="email" size="30" onblur="checkEmail();"/> //path的值必須和accountVo這個對象的屬性一致spring-mvc
<form:errors path="email" cssClass="errorMsg"></form:errors> session
//這裏省略了表單的其餘元素, 直接來提交按鈕 mvc
<input type=" button" id="saveAccount" value='<fmt:message key="button.next" />' onclick="submitAccount ('accountVo')"/>
//這裏徹底可使用type=「submit」, 這裏使用button能夠截獲提交事件, 並在提交以前先作JS層面的驗證
</form:form>
Note: 使用上面這些標籤, 必須引入Spring 的 form標籤庫:<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
你們還看到咱們使用了JSTL的fmt標籤庫(國際化), 這個也要引入<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>, 其實咱們也徹底能夠用<form message>標籤來作國際化的。這裏我還想說一個東西:readonly這個屬性根本起不到只讀的做用, 徹底能夠被修改,可是使用disable屬性後,這個表單元素就沒法放到accountVo這個對象並提交了, 糾結!
2. 這裏是個不完整的驗證類AccountValidator, 注意,咱們沒有實現Validator接口
public class AccountValidator {
public void validate(AccountVo accountVo, Errors errors) {
String email = accountVo.getEmail();
if (!StringUtils.hasLength(email)) {
errors.rejectValue("email", "validate.email.empty", "郵箱不能爲空");//這個函數有好幾個重載的變體
}
}
}
Note: Errors這個接口有好幾個rejectValue()函數, 它們是能夠支持國際化的。 好比, 上面這個例子表示, 錯誤的字段(filed)是「email」, errorCode是「validate.email.empty」, 與資源文件對應, 第三個是defaultMessage。不少國際化當中會帶有參數, rejectValue其中的一個重載函數就是 rejectValue( String field, String errorCode, Object[] errorArgs, String defaultMessage)。
3. 最後是AccountController
@Controller//基於註解, 聲明這是一個controller
@RequestMapping(value="/account") //表示總的路徑
@SessionAttributes("account") //表示account對象將會存入session當中, //默認狀況下model.addAttribute(account)將會把account對象放入request當中, 而且屬性名爲「account」
public class AccountFormController {
@RequestMapping(value = "/add", method = RequestMethod.POST)
public String addAccount( @ModelAttribute("accountVo") AccountVo accountVo,
BindingResult result, //這裏面,BindResult result必須緊跟着前面的@ModelAttribute, 不然會出錯
HttpServletResponse response,
HttpSession session, Model model) {
log.debug(accountVo.toString());
if(isExist(accountVo)){
log.debug("Opps, 這個email已經註冊過了!");
result.rejectValue("email", "misFormat", "這個email已經註冊過了!");
return "account/addAccount";
}else{
new AccountValidator().validate(accountVo, result);
if( result.hasErrors()){
log.debug("表單數據有誤, 從新填寫"+accountVo);
model.addAttribute("accountVo",accountVo);//把accountVo對象返回到頁面, 這樣不至於表單被清空了
return "account/addAccount";//返回到註冊頁面,同時,這裏會自動將驗證錯誤信息返回到JSP頁面, 怎麼返回呢?看後面!
}
//這裏會作不少數據庫的操做, 省略
}
} //end of login()
}//end of controller
Note: 這裏須要特別注意幾個問題:1.函 數形參 BindResult result 必須緊跟着前面的@ModelAttribute, 不然會出異常; 2. @ModelAttribute("accountVo") AccountVo accountVo, 這個參數與JSP頁面的<form:form modelAttribute="accountVo" action="${actionUrl}" method="post">對應
4. 進階一下, 看看驗證錯誤信息對象是怎麼傳遞到頁面的
這 一切看起來都很完美, 可是有時候出於設計的緣由, 咱們不得不使用redirect, 對, 就是重定向! 就是這個東西讓我對Spring MVC有了一點很差的印象, 特別是結合了sitemesh以後。這個先打住, 我們仍是說驗證錯誤怎麼傳給重定向以後的JSP頁面吧。
其實也簡單, 我們能夠先把錯誤對象放入session當中, 而後在另外一個Controller裏把它取出來, 而後再返回到相應的JSP頁面就好了!
對!可是,這裏要注意了, BindingResult這個對象是自動傳入JSP的, 咱們不知道應該把它放在request裏面呢仍是session裏面, 或者其餘的地方, 以及屬性名叫什麼。這個就是我昨天晚上糾結的問題, 最後看了一下Spring 的源代碼, 終於稍微清楚了一點兒。下面直接上代碼,而後解釋。
if(session.getAttribute("BindingResult.accountVo") != null){
//放到session和request裏面, 不論attr name設置成什麼都不行
//只有這樣才能把bindingresult的錯誤信息傳到JSP頁面
String errorAttrName = " org.springframework.validation.BindingResult.accountenterpriseVo";
model.addAttribute(errorAttrName, session.getAttribute("BindingResult.accountVo"));
session.removeAttribute("BindingResult.enterpriseVo");
}
首先, 驗證錯誤對象 BindingResult 必須放入 org.springframework.ui. Model 當中返回給JSP頁面。放到request和session當中都沒用。
第二,這個屬性名是 BindingResult.getClass().getName + 「.」 + targetName, 也就是上面那一長串, 其中targerName對應着JSP頁面的表單的modelAttribute, 即<form:form modelAttribute="accountVo" action="${actionUrl}" method="post">中的accountVo。 對了, 順便說一下, accountVo同時仍是表單的id, 你們能夠用firefox的firebug查看頁面元素。<form:error>標籤也會被翻譯成
<span class="errorMsg" id="email.errors">郵箱格式不正確!</span> //若是是英文瀏覽器, 「郵箱格式不正確!」就會使英文版本的。
好的, 就先寫到這裏了。