Spring MVC數據校驗與國際化

1、 JSR-303

JSR-303 是JAVA EE 6 中的一項子規範,叫做Bean Validation,官方參考實現是Hibernate Validator。
此實現與Hibernate ORM 沒有任何關係。JSR 303 用於對Java Bean 中的字段的值進行驗證。

Spring MVC 3.x之中也大力支持 JSR-303,可以在控制器中對錶單提交的數據方便地驗證。

JSR 303內置的約束規則:

  • @AssertTrue / @AssertFalse

驗證適用字段:boolean
註解說明:驗證值是否爲true / false
屬性說明:-

  • @DecimalMax / @DecimalMin

驗證適用字段:BigDecimal,BigInteger,String,byte,short,int,long
註解說明:驗證值是否小於或者等於指定的小數值,要注意小數存在精度問題
屬性說明:公共

  • @Digits

驗證適用字段:BigDecimal,BigInteger,String,byte,short,int,long
註解說明:驗證值的數字構成是否合法
屬性說明:integer:指定整數部分的數字的位數。fraction: 指定小數部分的數字的位數。

  • @Future / @Past

驗證適用字段:Date,Calendar
註解說明:驗證值是否在當前時間之後 / 之前
屬性說明:公共

  • @Max / @Min

驗證適用字段:BigDecimal,BigInteger,String,byte,short,int,long
註解說明:驗證值是否小於或者等於指定的整數值
屬性說明:公共

  • @NotNull / @Null

驗證適用字段:引用數據類型
註解說明:驗證值是否爲非空 / 空
屬性說明:公共

  • @Pattern

驗證適用字段:String
註解說明:驗證值是否配備正則表達式
屬性說明:regexp:正則表達式flags: 指定Pattern.Flag 的數組,表示正則表達式的相關選項。

  • @Size

驗證適用字段:String,Collection,Map,數組
註解說明:驗證值是否滿足長度要求
屬性說明:max:指定最大長度,min:指定最小長度。

  • @Valid

驗證適用字段:引用類型
註解說明:驗證值是否需要遞歸驗證
屬性說明:無

使用Spring MVC 和 JSR-303的標註做表單提交的服務器端驗證時,@Valid 標註的Command對象和BindingResult參數一定要緊挨着。要不然數據綁定錯誤直接拋異常,不會封裝成一個BindingResult對象。

2、Spring MVC數據校驗

<mvc:annotation-driven/>會默認裝配好一個LocalValidatorFactoryBean,通過在處理方法的入參上標註@Valid註解就可讓Spring MVC在完成數據綁定後執行數據校驗操作。

A、需要的額外的JAR包
除了Spring MVC本身的JAR包外,我們還需要一些額外的JAR包。
這裏寫圖片描述

B、添加JSR 303註解

package cn.framelife.mvc.entity;

import java.util.Date;

import javax.validation.constraints.DecimalMax;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.NumberFormat;

public class User implements java.io.Serializable {

    private Integer id;

    /*
     * 測試的時候,發現在頁面獲取到的數據傳到User模式後,都是非空的。
     */
    @NotNull(message = "用戶名不能爲空")
    private String username;

    @Size(min = 2, max = 6, message = "長度是2-6之間")
    private String password;

    @Past(message = "必須是一個過去的時間")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date birthday;

    @DecimalMin(value = "1000.00", message = "工資必須大於1000.00")
    @DecimalMax(value = "10000.00", message = "工資必須小於10000.00")
    @NumberFormat(pattern = "#,###.##")
    private long salary;

    @Pattern(regexp = "1[3|4|5|8][0-9]\\d{4,8}", message = "手機號碼不匹配")
    private String phone;

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public long getSalary() {
        return salary;
    }

    public void setSalary(long salary) {
        this.salary = salary;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

C、Controller中的處理

@Controller
@RequestMapping("/user")
public class UserControl {

    /**
     * 此方法是用於第一次給頁面添加一個user模型數據的
     */
    @RequestMapping(value="/add",method = RequestMethod.GET)
    public ModelAndView initForm(){
        User user = new User();
        return new ModelAndView("/add").addObject(user); 
    }

    /**
     * 給入參的模型對象User加入@Valid註解,說明這個對象裏面的屬性需要校驗
     * BindingResult入參是用以判斷上面的校驗是否出錯
     */
    @RequestMapping("create")
    public ModelAndView createUser(@Valid User user,BindingResult bindingResult){
        ModelAndView view = new ModelAndView();
        System.out.println(user.getUsername()+"----");

        //如果校驗有問題,跑回原來的add.jsp頁面,如果沒問題跑到success.jsp頁面
        if(bindingResult.hasErrors()){
            view.setViewName("/add");
        }else{
            view.setViewName("/success");
        }

        return view;
    }
}

D、頁面輸入及輸出

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!-- 導入spring的表單標籤庫 -->
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">

    <title>增加</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->
  </head>

  <body>

    <!-- 在使用表單標籤的時候需要獲取到一個user模型數據,那我們不能直接訪問頁面(通過/user/add.abc訪問),必須通過訪問一次服務器,獲取到一個user數據模型後才行,否則會出錯 -->
    <form:form modelAttribute="user" action="user/create.abc">
        <!-- 輸出所有的錯誤信息 -->
        <form:errors path="*" /><br/>
        <hr/>

        <!-- 輸出單個錯誤信息 -->
        <form:errors path="username" ></form:errors><br/>
        用戶名:<form:input path="username"/><br/>

        <form:errors path="password" ></form:errors><br/>
        密 碼:<form:password path="password"/><br/>

        <form:errors path="birthday" ></form:errors><br/>
        生日:<form:input path="birthday"/><br/>

        <form:errors path="salary" ></form:errors><br/>
        工資:<form:input path="salary"/><br/>

        <form:errors path="phone" ></form:errors><br/>
        電話:<form:input path="phone"/><br/>

        <input type="submit">
    </form:form>
  </body>
</html>

3、通過國際化資源顯示錯誤信息

A、校驗屬性

    /*
     * 使用資源文件,這裏不再需要message參數
     */
    @Pattern(regexp = "1[3|4|5|8][0-9]\\d{4,8}")
    private String phone;

B、資源文件(src下的messages.properties)

Pattern.user.phone=\u624B\u673A\u53F7\u7801\u4E0D\u5339\u914D

上面鍵值對中,
鍵是校驗類javax.validation.constraints.Pattern的類名+被校驗的模型對象名+屬性名
值是”手機號碼不匹配”

C、配置本地化資源文件(mvc-servlet.xml)

<!-- 配置國際化資源文件 -->
<!-- 
        ReloadableResourceBundleMessageSource加載時,默認使用DefaultResourceLoader,他會先判斷資源path是否帶有classpath:前綴,如果有,用ClassPathResource去加載資源文件,如果沒有試着用文件協議的url去訪問,再沒有就在contextPath即WEB-INF下查找
     -->
    <bean id="messageSource"
        class="org.springframework.context.support.ReloadableResourceBundleMessageSource"
        p:basename="classpath:messages">
    </bean>

D、顯示

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!-- 導入spring的表單標籤庫 -->
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">

    <title>增加</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->
  </head>

  <body>

    <!-- 在使用表單標籤的時候需要獲取到一個user模型數據,那我們不能直接訪問頁面(通過/user/add.abc訪問),必須通過訪問一次服務器,獲取到一個user數據模型後才行,否則會出錯 -->
    <form:form modelAttribute="user" action="user/create.abc">
        <!-- 輸出所有的錯誤信息 -->
        <form:errors path="*" /><br/>
        <hr/>

        <!-- 輸出單個錯誤信息 -->
        <form:errors path="username" ></form:errors><br/>
        用戶名:<form:input path="username"/><br/>

        <form:errors path="password" ></form:errors><br/>
        密 碼:<form:password path="password"/><br/>

        <form:errors path="birthday" ></form:errors><br/>
        生日:<form:input path="birthday"/><br/>

        <form:errors path="salary" ></form:errors><br/>
        工資:<form:input path="salary"/><br/>

        <form:errors path="phone" ></form:errors><br/>
        電話:<form:input path="phone"/><br/>

        <input type="submit">
    </form:form>
  </body>
</html>
發佈了146 篇原創文章 · 獲贊 130 · 訪問量 78萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章