User.javahtml
public class User { @DateTimeFormat(pattern="yyyy-MM-dd") private Date birth; . . }
例如 User類 的屬性 birth 是一個 Date 類型,必須在實體類中聲明格式,不然不能從表單提交到 @Controller
註解的類中對應的方法處理。java
JSR 303是 Java 爲 Bean 數據合法性校驗提供給的標準框架,已經包含在 JavaEE6.0中、JSR 303經過在Bean 屬性中標註相似 @NotNull @Max 等標準的註解指定校驗規則,並經過標準的驗證接口對 Bean進行驗證mysql
hibernate Validator 是 JSR 303 的一個參考實現,除了支持全部標準的校驗註解外,
它還支持一些擴展註解,下面是詳細的註解列表git
JSR 303中含有的註解 @Null 被註釋的元素必須爲 null @NotNull 被註釋的元素必須不爲 null @AssertTrue 被註釋的元素必須爲 true @AssertFalse 被註釋的元素必須爲 false @Min(value) 被註釋的元素必須是一個數字,其值必須大於等於指定的最小值 @Max(value) 被註釋的元素必須是一個數字,其值必須小於等於指定的最大值 @DecimalMin(value) 被註釋的元素必須是一個數字,其值必須大於等於指定的最小值 @DecimalMax(value) 被註釋的元素必須是一個數字,其值必須小於等於指定的最大值 @Size(max=, min=) 被註釋的元素的大小必須在指定的範圍內 @Digits (integer, fraction) 被註釋的元素必須是一個數字,其值必須在可接受的範圍內 @Past 被註釋的元素必須是一個過去的日期 @Future 被註釋的元素必須是一個未來的日期 @Pattern(regex=,flag=) 被註釋的元素必須符合指定的正則表達式 ------------------------------ Hibernate Validator 附加的註解 @NotBlank(message =) 驗證字符串非null,且長度必須大於0 @Email 被註釋的元素必須是電子郵箱地址 @Length(min=,max=) 被註釋的字符串的大小必須在指定的範圍內 @NotEmpty 被註釋的字符串的必須非空 @Range(min=,max=,message=) 被註釋的元素必須在合適的範圍內
spring 4.0擁有本身的數據庫校驗框架,同時支持JSR 303標準校驗框架。
Spring 在進行數據綁定時,可同時調用校驗框架完成校驗工做。在SpringMVC中,可直接經過註解驅動的方式進行數據校驗web
Spring 的LocalValidatorFactoryBean 即實現了Spring的Validator 接口,也實現了JSR 303 的Validator 接口。 只要在Spring 容器中定義一個LocalValidatorFactoryBean ,便可將其注入到須要數據校驗的 Bean中。
Spring 自己並無提供JSR 303 的實現,全部必須將JSR 303的實現者的jar 包(HIbernate Validator jar包)導入到項目中正則表達式
<mvc:annotation-driven>會默認裝配好一個LocalValidatorFactoryBean,經過在處理方法的入參上標註 @Valid 註解便可讓 SpringMVC 在完成數據綁定後執行數據校驗工做 在已經標註了 JSR 303 註解的表單、命令對象前標註一個@Valid,SpringMVC框架在將請求參數綁定到該入參對象後,就會調用校驗框架根據註解聲明的校驗規則實施校驗
SpringMVC 除了會將表單、命令對象的校驗結果保存到對應的 BindingResult 或Error對象外,還會將全部校驗結果保存到「隱含模型」。
即便處理方法中的簽名中沒有對應於表單/命名對象的結果入參,校驗結果也會保存在「隱含對象」中。spring
(好比User的IDCard沒有指定校驗的註解,能夠它要求是Float型,輸入String型數據,發生類型錯誤也會保存到隱含對象中輸出)
隱含模型中的全部數據最終將經過HttpServletRequest的屬性列表暴露個JSP視圖對象,所以在JSP中能夠獲取錯誤信息
在JSP頁面上可經過下面的標籤顯示sql
<form:errors path="*" /> 顯示錶單全部錯誤 <form:errors path="user* /> 顯示全部以user爲前綴的屬性對應的錯誤 <form:errors path="username"/> 顯示特定表單對象屬性的錯誤
當使用 SpringMVC 標籤顯示錯誤消息時,SpringMVC 會查看WEB上下文是否裝配了對應的國際化消息,若是沒有,則顯示默認的錯誤消息,不然使用國際化消息數據庫
若數據類型轉換或數據格式轉換時發生錯誤,或該有的參數不存在,或調用處理方法時發生錯誤,都會在隱含模型建立錯誤消息,其錯誤代碼前綴(在國際化文件中配置)說明以下:spring-mvc
required:必要的參數不存在。 @RequiredParam("param1")標註了一個入參,可是該參數不存在 typeMismatch :在數據綁定是,發生數據類型不匹配的問題 methodInvocation :SpringMVC 在調用處理方法時發生了錯誤
例如:
i18n_zh_CN.properties
NotEmpty.user.name= \u59D3\u540D\u4E0D\u80FD\u4E3A\u7A7A\u554A Email.user.email= \u90AE\u7BB1\u683C\u5F0F\u4E0D\u5BF9\u54E6 Past.user.birth= \u4F60\u51FA\u751F\u65E5\u671F\u5728\u660E\u5929\uFF1F typeMismatch.user.birth=Birth\u4E0D\u662F\u4E00\u4E2A\u65E5\u671F
在SpringMVC中配置
<!--配置國際化資源文件--> <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basename" value="i18n"></property> </bean>
紅色標註的爲 HIbernate Validator jar包
官網下載地址 http://hibernate.org/validator/
解壓後,使用dist
和\dist\lib\required
兩個目錄下部分jar包源代碼下載(包含jar包):http://download.csdn.net/detail/peng_hong_fu/9707572
Eclipse版本 Neon.1a Release (4.6.1) Spring 4.3.4 hibernate-validator-5.3.3
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>springmvc-dataFormat</display-name> <!-- 防止中文參數亂碼 放在前面 --> <filter> <filter-name>SetCharacterEncoding</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> <!-- 強制進行轉碼 --> </init-param> </filter> <filter-mapping> <filter-name>SetCharacterEncoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!--配置DispatcherServlet --> <servlet> <servlet-name>springDispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 配置DispatcherServlet 的一個初始化參數:配置SpringMVC 配置文件的位置和名稱 --> <!-- 實際上也能夠不經過 contextConfigLocation 來配置 SpringMVC 的配置文件 默認的配置文件路徑爲 /WEB-INF/{servlet-name}-servlet.xml 能夠去除下面的<init-param> --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <!-- Map all requests to the DispatcherServlet for handling --> <servlet-mapping> <servlet-name>springDispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
springmvc.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd"> <context:component-scan base-package="com.jxust.dataformat"></context:component-scan> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/"></property> <property name="suffix" value=".jsp"></property> </bean> <mvc:default-servlet-handler/> <mvc:annotation-driven></mvc:annotation-driven> <!--配置國際化資源文件--> <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basename" value="i18n"></property> </bean> </beans>
<mvc:annotation-driven/>的做用
<mvc:annotation-driven></mvc:annotation-driven> 會自動註冊 RequestMappingHandlerMapping、RequestMappingHandlerAdapter 和ExceptionHandlerExceptionResolver三個bean 還提供瞭如下的支持 -支持使用ConversionService 示例對錶單參數進行類型轉換 -支持使用@NumberFormatannotation、@DateTimeFormat 註解完成數據類型的格式化 -支持使用 @Valid 註解對 JavaBean 實例進行JSR 303驗證 -支持使用@RequestBody 和 @ResponseBody 註解
User.java
package com.jxust.dataformat.entity; import java.util.Date; import javax.validation.constraints.Past; import org.hibernate.validator.constraints.Email; import org.hibernate.validator.constraints.NotEmpty; import org.hibernate.validator.constraints.Range; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.NumberFormat; public class User { @Range(min=100,max=11,message="內容必須在11到100之間") private Integer id; @NotEmpty private String name; @Email private String email; @NumberFormat(pattern="#,###,###,#") private Float idCard; @Past @DateTimeFormat(pattern="yyyy-MM-dd") private Date birth; //birth 和idCard 的格式聲明,輸入的格式就必須匹配 //省略 getter and setter @Override public String toString() { return "User [id=" + id + ", name=" + name + ", email=" + email + ", idCard=" + idCard + ", birth=" + birth + "]"; } }
DataFormatHandler.java
package com.jxust.dataformat.handler; import java.util.Map; import javax.validation.Valid; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; import org.springframework.validation.FieldError; import org.springframework.web.bind.annotation.RequestMapping; import com.jxust.dataformat.entity.User; @Controller public class DataFormatHandler { /** * 跳轉到輸入頁面input.jsp * * @param map * @return */ @RequestMapping("/input") public String dataformat(Map<String, Object> map) { /** * 對應 form表單的 modelAttribute="user" * 由於表單默認是要回顯的,這裏傳入一個空對象 */ map.put("user", new User()); return "input"; } /** * input界面提交表單數據的處理方法,在這個方法中進行數據校驗 * 注意: * 須要校驗 bean 對象和其綁定結果對象或錯誤結果(Error) * @Valid User user,BindingResult result 兩個入參必須成對出現,中間不容許其餘入參分隔 * @param user * @param result * @return */ @RequestMapping("/testinput") public String testinput(@Valid User user, BindingResult result) { System.out.println(user.toString()); /** * 類型轉換失敗時的錯誤信息輸出 */ if (result.getErrorCount() > 0) { System.out.println("出錯了..."); for (FieldError error : result.getFieldErrors()) { System.out.println(error.getField() + ":" + error.getDefaultMessage()); } // 驗證出錯,則轉向特定的頁面(這裏是以前的輸入的頁面) return "input"; } return "success"; } }
SpringMVC 是經過對處理方法簽名的規則來保存校驗結果的,前一個表單、命令對象的校驗結果保存到隨後的入參中,這個保存校驗結果的入參必須是 BindingResult 或 Errors類型(這裏使用的是BindingResult),這兩個類都位於 org.springframework.validation
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!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> </head> <body> <a href="input">To Input</a> </body> </html>
input.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ 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>Insert title here</title> </head> <body> <!-- 1.數據校驗,生日不能是今日以後 1)如何校驗,註解 ①使用 JSR 303 驗證標準 ② 加入 hibernate validator 驗證框架的jar包 ③ 在SpringMVC 配置文件中添加 <mvc:annotation-drivern/> ④ 須要在bean的屬性上添加對應的註解 ⑤ 在目標方法 bean類型的前面添加 @Valid 註解 2)驗證出錯轉向哪一個頁面? 注意:須要校驗的 bean 對象和其綁定結果對象或錯誤對象時成對出現的,他們之間不容許其餘的入參 3)錯誤消息?如何顯示,如何實現國際化 --> <form:form action="testinput" method="post" modelAttribute="user"> <form:errors path="*"></form:errors><br><!-- 顯示全部錯誤消息 --> id:<form:input path="id"/> <form:errors path="id"></form:errors><br> name:<form:input path="name"/> <form:errors path="name"></form:errors><br> email:<form:input path="email"/> <form:errors path="email"></form:errors><br> idCard:<form:input path="idCard"/> <form:errors path="idCard"></form:errors><br> birth:<form:input path="birth"/> <form:errors path="birth"></form:errors><br> <input type="submit" value="提交"/> </form:form> </body> </html>
success.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!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>Insert title here</title> </head> <body> <h2>success</h2> </body> </html>
i18n_zh_CN.properties
NotEmpty.user.name= \u59D3\u540D\u4E0D\u80FD\u4E3A\u7A7A\u554A Email.user.email= \u90AE\u7BB1\u683C\u5F0F\u4E0D\u5BF9\u54E6 Past.user.birth= \u4F60\u51FA\u751F\u65E5\u671F\u5728\u660E\u5929\uFF1F typeMismatch.user.birth=Birth\u4E0D\u662F\u4E00\u4E2A\u65E5\u671F
聲明瞭格式,才能正常的使用 @DateTimeFormat(pattern="yyyy-MM-dd") private Date birth; 輸出的內容爲: User [id=1, name=ee, email=ee, idCard=12134.0, birth=Sun Sep 09 00:00:00 CDT 1990] --------------------- 聲明瞭birth和idCard的格式,故意輸入錯誤格式,輸出的內容爲: User [id=null, name=, email=ee, idCard=null, birth=null] 出錯了... birth:Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'birth'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@javax.validation.constraints.Past @org.springframework.format.annotation.DateTimeFormat java.util.Date] for value '2033-09-'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [2033-09-] idCard:Failed to convert property value of type 'java.lang.String' to required type 'java.lang.Float' for property 'idCard'; nested exception is java.lang.NumberFormatException: For input string: "ee" --------------------- 使用了@Valid,格式校驗啓動,故意輸入錯誤格式,輸出的內容爲: User [id=null, name=, email=ee, idCard=null, birth=Fri Sep 09 00:00:00 CST 2033] 出錯了... email:不是一個合法的電子郵件地址 name:不能爲空 birth:須要是一個過去的時間