Java Bean Validation(參數校驗) 最佳實踐

 

37. Validation
The method validation feature supported by Bean Validation 1.1 is automatically enabled as long as a JSR-303 implementation (such as Hibernate validator) is on the classpath. This lets bean methods be annotated with javax.validation constraints on their parameters and/or on their return value. Target classes with such annotated methods need to be annotated with the @Validated annotation at the type level for their methods to be searched for inline constraint annotations.html

For instance, the following service triggers the validation of the first argument, making sure its size is between 8 and 10:前端

@Service
@Validated
public class MyBean {

    public Archive findByCodeAndAuthor(@Size(min = 8, max = 10) String code,
            Author author) {
        ...
    }

}

https://docs.spring.io/spring-boot/docs/2.1.10.RELEASE/reference/html/boot-features-validation.htmljava

 

 

 

轉載來自:http://www.cnblogs.comgit

參數校驗是咱們程序開發中必不可少的過程。用戶在前端頁面上填寫表單時,前端js程序會校驗參數的合法性,當數據到了後端,爲了防止惡意操做,保持程序的健壯性,後端一樣須要對數據進行校驗。後端參數校驗最簡單的作法是直接在業務方法裏面進行判斷,當判斷成功以後再繼續往下執行。但這樣帶給咱們的是代碼的耦合,冗餘。當咱們多個地方須要校驗時,咱們就須要在每個地方調用校驗程序,致使代碼很冗餘,且不美觀。spring

那麼如何優雅的對參數進行校驗呢?JSR303就是爲了解決這個問題出現的,本篇文章主要是介紹 JSR303,Hibernate Validator 等校驗工具的使用,以及自定義校驗註解的使用。後端

校驗框架介紹

JSR303 是一套JavaBean參數校驗的標準,它定義了不少經常使用的校驗註解,咱們能夠直接將這些註解加在咱們JavaBean的屬性上面,就能夠在須要校驗的時候進行校驗了。註解以下:api

 

Spring validtor 一樣擴展了jsr303,並實現了方法參數和返回值的校驗數組

Spring 提供了MethodValidationPostProcessor類,用於對方法的校驗app

代碼實現

添加JAR包依賴

在pom.xml中添加以下依賴:框架

<!--jsr 303--> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>1.1.0.Final</version> </dependency> <!-- hibernate validator--> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.2.0.Final</version> </dependency>

 

最簡單的參數校驗

一、Model 中添加校驗註解

public class Book { private long id; /** * 書名 */ @NotEmpty(message = "書名不能爲空") private String bookName; /** * ISBN號 */ @NotNull(message = "ISBN號不能爲空") private String bookIsbn; /** * 單價 */ @DecimalMin(value = "0.1",message = "單價最低爲0.1") private double price; // getter setter ....... }

 

二、在controller中使用此校驗

/**
     * 添加Book對象
     * @param book
     */ @RequestMapping(value = "/book", method = RequestMethod.POST) public void addBook(@RequestBody @Valid Book book) { System.out.println(book.toString()); }

 

當訪問這個post接口時,若是參數不符合Model中定義的話,程序中就回拋出400異常,並提示錯誤信息。

自定義校驗註解

雖然jSR303和Hibernate Validtor 已經提供了不少校驗註解,可是當面對複雜參數校驗時,仍是不能知足咱們的要求,這時候咱們就須要 自定義校驗註解。

下面以「List數組中不能含有null元素」爲實例自定義校驗註解

一、註解定義以下:

package com.beiyan.validate.annotation; import javax.validation.Constraint; import javax.validation.Payload; import java.lang.annotation.*; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.RetentionPolicy.RUNTIME; /** * 自定義參數校驗註解 * 校驗 List 集合中是否有null 元素 */ @Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Constraint(validatedBy = ListNotHasNullValidatorImpl.class)////此處指定了註解的實現類爲ListNotHasNullValidatorImpl public @interface ListNotHasNull { /** * 添加value屬性,能夠做爲校驗時的條件,若不須要,可去掉此處定義 */ int value() default 0; String message() default "List集合中不能含有null元素"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; /** * 定義List,爲了讓Bean的一個屬性上能夠添加多套規則 */ @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER}) @Retention(RUNTIME) @Documented @interface List { ListNotHasNull[] value(); } }

 

二、註解實現類: 

package com.beiyan.validate.annotation; import org.springframework.stereotype.Service; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import java.util.List; /** * 自定義註解ListNotHasNull 的實現類 * 用於判斷List集合中是否含有null元素 */ @Service public class ListNotHasNullValidatorImpl implements ConstraintValidator<ListNotHasNull, List> { private int value; @Override public void initialize(ListNotHasNull constraintAnnotation) { //傳入value 值,能夠在校驗中使用 this.value = constraintAnnotation.value(); } public boolean isValid(List list, ConstraintValidatorContext constraintValidatorContext) { for (Object object : list) { if (object == null) { //若是List集合中含有Null元素,校驗失敗 return false; } } return true; } }

 

三、model添加註解:

public class User { //其餘參數 ....... /** * 所擁有的書籍列表 */ @NotEmpty(message = "所擁有書籍不能爲空") @ListNotHasNull(message = "List 中不能含有null元素") @Valid private List<Book> books; //getter setter 方法....... }

 

使用方法同上,在在須要校驗的Model上面加上@Valid 便可

分組驗證

對同一個Model,咱們在增長和修改時對參數的校驗也是不同的,這個時候咱們就須要定義分組驗證,步驟以下

一、定義兩個空接口,分別表明Person對象的增長校驗規則和修改校驗規則

/**
 * 能夠在一個Model上面添加多套參數驗證規則,此接口定義添加Person模型新增時的參數校驗規則
 */ public interface PersonAddView { } /** * 能夠在一個Model上面添加多套參數驗證規則,此接口定義添加Person模型修改時的參數校驗規則 */ public interface PersonModifyView { }

 

二、Model上添加註解時使用指明所述的分組

public class Person { private long id; /** * 添加groups 屬性,說明只在特定的驗證規則裏面起做用,不加則表示在使用Deafault規則時起做用 */ @NotNull(groups = {PersonAddView.class, PersonModifyView.class}, message = "添加、修改用戶時名字不能爲空", payload = ValidateErrorLevel.Info.class) @ListNotHasNull.List({ @ListNotHasNull(groups = {PersonAddView.class}, message = "添加上Name不能爲空"), @ListNotHasNull(groups = {PersonModifyView.class}, message = "修改時Name不能爲空")}) private String name; @NotNull(groups = {PersonAddView.class}, message = "添加用戶時地址不能爲空") private String address; @Min(value = 18, groups = {PersonAddView.class}, message = "姓名不能低於18歲") @Max(value = 30, groups = {PersonModifyView.class}, message = "姓名不能超過30歲") private int age; //getter setter 方法...... }

 

三、啓用校驗

此時啓用校驗和以前的不一樣,須要指明啓用哪一組規則

/**
     * 添加一個Person對象
     * 此處啓用PersonAddView 這個驗證規則
     * 備註:此處@Validated(PersonAddView.class) 表示使用PersonAndView這套校驗規則,若使用@Valid 則表示使用默認校驗規則,
     * 若兩個規則同時加上去,則只有第一套起做用
     */ @RequestMapping(value = "/person", method = RequestMethod.POST) public void addPerson(@RequestBody @Validated({PersonAddView.class, Default.class}) Person person) { System.out.println(person.toString()); } /** * 修改Person對象 * 此處啓用PersonModifyView 這個驗證規則 */ @RequestMapping(value = "/person", method = RequestMethod.PUT) public void modifyPerson(@RequestBody @Validated(value = {PersonModifyView.class}) Person person) { System.out.println(person.toString()); }

 

Spring validator 方法級別的校驗

JSR和Hibernate validator的校驗只能對Object的屬性進行校驗,不能對單個的參數進行校驗,spring 在此基礎上進行了擴展,添加了MethodValidationPostProcessor攔截器,能夠實現對方法參數的校驗,實現以下:

一、實例化MethodValidationPostProcessor

@Bean public MethodValidationPostProcessor methodValidationPostProcessor() { return new MethodValidationPostProcessor(); }

 

二、在所要實現方法參數校驗的類上面添加@Validated,以下

@RestController @Validated public class ValidateController { }

 

三、在方法上面添加校驗規則:

@RequestMapping(value = "/test", method = RequestMethod.GET) public String paramCheck(@Length(min = 10) @RequestParam String name) { System.out.println(name); return null; }

 

當方法上面的參數校驗失敗,spring 框架就回拋出異常

{ "timestamp": 1476108200558, "status": 500, "error": "Internal Server Error", "exception": "javax.validation.ConstraintViolationException", "message": "No message available", "path": "/test" }

今後能夠優雅的對參數進行校驗了 

寫在後面的話:

本篇文章只列舉了經常使用的幾種校驗方法,其實關於校驗的內容還有不少:

校驗信息的國際化顯示,

組合參數校驗,

message中使用EL表達式,

將校驗信息綁定到ModelAndView等,這裏就不一一列出了,下面這幾篇文章寫的也不錯,讀者能夠參考:

將校驗信息綁定到ModelAndView    http://www.voidcn.com/blog/983836…

集成Bean Validation 1.1(JSR-349)到SpringMVC   my.oschina.net/qjx1208/blo…

本文的所有代碼已上傳開源中國git倉庫: git.oschina.net/beiyan/Vali…

 

http://www.gitout.cn/?p=2532

相關文章
相關標籤/搜索