SpringMVC 數據的格式化、JSR 303數據校驗和國際化

1 數據的格式化

User.javahtml

public class User {

    @DateTimeFormat(pattern="yyyy-MM-dd")
    private Date birth;
    .
    .
}

例如 User類 的屬性 birth 是一個 Date 類型,必須在實體類中聲明格式,不然不能從表單提交到 @Controller註解的類中對應的方法處理。java

2 JSR 303數據校驗

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=)  被註釋的元素必須在合適的範圍內

3 JSR 303數據校驗在Spring中使用

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框架在將請求參數綁定到該入參對象後,就會調用校驗框架根據註解聲明的校驗規則實施校驗

4 校驗信息如何顯示

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"/> 顯示特定表單對象屬性的錯誤

5 國際化

當使用 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>

6 項目結構

這裏寫圖片描述

這裏寫圖片描述

紅色標註的爲 HIbernate Validator jar包 
官網下載地址 http://hibernate.org/validator/ 
解壓後,使用dist\dist\lib\required兩個目錄下部分jar包

源代碼下載(包含jar包):http://download.csdn.net/detail/peng_hong_fu/9707572

7 版本信息

Eclipse版本 Neon.1a Release (4.6.1)
Spring 4.3.4
hibernate-validator-5.3.3

源代碼

web.xml和SpringMVC文件配置

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
                + "]";
    }   
}

Controller

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

JSP頁面

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

這裏寫圖片描述

筆記.txt

聲明瞭格式,才能正常的使用
    @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:須要是一個過去的時間

源代碼下載

下載地址:http://download.csdn.net/detail/peng_hong_fu/9707572

相關文章
相關標籤/搜索