SpringBoot入門實踐(六)-JSR-349實現請求參數驗證

 個人博客:蘭陵笑笑生,歡迎瀏覽博客!java

 上一章 SpringBoot入門實踐(五)-開源日誌框架介紹當中,咱們介紹了經常使用的開源日誌框架。本期總結我在項目中是如何使用JSR實現請求參數的驗證的。git

前言

 從Spring4開始,已經實現了對JSR-349(Bean Validation,是JSR303的升級 )的全面支持,Bean Validation API在javax。validation.CONSTRAINTS 中以JAVA註解的形式定義了一組可應用於域對象的約束,另外可使用註解開發和應用自定義驗證器,如類級驗證器。web

1、Spring中配置Bean Validation的支持

使用方式:

  • 定義對象屬性的驗證約束:

public class Singer {  
    @NotNull(message = "名稱不能爲空")  
    @Size(min = 2, max = 5)   
    private String fistName;  
    private String lastName;   
    @NotNull(message = "性別不能爲空")  
    private Genre genre;
    ....
}
  • 配置一個類型爲LocalValidatorFactoryBean 的bean

package com.miroservice.chapter2.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;@Configuration@ComponentScan("com.miroservice")
public class AppConfig { 
    /**     * 默認會在類路徑下搜索Hibernate validator的庫     * @return     */  
    @Bean  
    LocalValidatorFactoryBean validator(){     
        return new LocalValidatorFactoryBean();  
    }
}
  • 建立一個驗證服務,一旦定義了LocalValidatorFactoryBean ,既能夠在應用程序任何位置注入Validator的實例

import com.miroservice.chapter2.pojo.Singer;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import javax.validation.ConstraintViolation;import javax.validation.Validator;import java.util.Set;
@Component
public class ValidateComponent {  
    /**     * 注入一個javax.validation.Validator 實例     */  
    @Autowired    
    private Validator validator;   
    
    public Set<ConstraintViolation<Singer>> validatorSinger(Singer singer) { 
        return validator.validate(singer);  
    }
}
  • 測試:

package com.miroservice.chapter2.web;
import com.miroservice.chapter2.config.AppConfig;
import com.miroservice.chapter2.pojo.Singer;
importorg.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
import javax.validation.ConstraintViolation;
import java.util.Set;

public class JSR349Demo { 
public static void main(String[] args) {   
GenericApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);   
ValidateComponent validateController = ctx.getBean(ValidateComponent.class);        Singer singer = new Singer();      
    singer.setFistName("j");    
    singer.setLastName("l");     
    singer.setGenre(null);      
    validatorSinger(singer, validateController);  
}    
    private static void validatorSinger(Singer singer, 
                                        ValidateComponent validateController) {  
        
        final Set<ConstraintViolation<Singer>> constraintViolations = validateController.validatorSinger(singer);    
        listVidlations(constraintViolations);    
    }  
    
    private static void listVidlations(Set<ConstraintViolation<Singer>> set) {     
        for (ConstraintViolation<Singer> v : set) {  
            System.out.print("property:" + v.getPropertyPath() + ",value:" 
                             + v.getInvalidValue() + ";error:" + v.getMessage());  
        } 
    }
}
  • 打印結果

file

2、經常使用的註解解釋

  • 1@Null 被註釋的元素必須爲 null
  • 2@NotNull 被註釋的元素必須不爲 null
  • 4 @AssertTrue 被註釋的元素必須爲 true
  • 5 @AssertFalse 被註釋的元素必須爲 false
  • 6 @Min(value) 被註釋的元素必須是一個數字,其值必須大於等於指定的最小值7
  • @Max(value) 被註釋的元素必須是一個數字,其值必須小於等於指定的最大值
  • 8 @DecimalMin(value) 被註釋的元素必須是一個數字,其值必須大於等於指定的最小值
  • 9 @DecimalMax(value) 被註釋的元素必須是一個數字,其值必須小於等於指定的最大值
  • 10 @Size(max=, min=) 被註釋的元素的大小必須在指定的範圍內
  • 11 @Digits (integer, fraction) 被註釋的元素必須是一個數字,其值必須在可接受的範圍內
  • 12 @Past 被註釋的元素必須是一個過去的日期
  • 13 @Future 被註釋的元素必須是一個未來的日期14
  • @Pattern(regex=,flag=) 被註釋的元素必須符合指定的正則表達式15
  • 16 Hibernate Validator 附加的 constraint
  • 17 @NotBlank(message =) 驗證字符串非null,且長度必須大於0
  • 18 @Email 被註釋的元素必須是電子郵箱地址
  • 19 @Length(min=,max=) 被註釋的字符串的大小必須在指定的範圍內
  • 20 @NotEmpty 被註釋的字符串的必須非空21
  • @Range(min=,max=,message=) 被註釋的元素必須在合適的範圍內

Hibernate Validator參考實現 http://hibernate.org/validator/

3、springBoot中web請求的POJO驗證

使用方式:

  • 定義對象屬性的驗證約束:

import javax.validation.constraints.NotNull;import javax.validation.constraints.Size;
public class Singer { 
    
    @NotNull(message = "名稱不能爲空")    
    @Size(min = 2, max = 5)  
    private String fistName;   
    
    private String lastName; 
    
    @NotNull(message = "性別不能爲空")   
    private Genre genre;
   ...   
}
  • 定義Controller

import com.miroservice.chapter2.common.HttpResponse;
import com.miroservice.chapter2.pojo.Singer;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;

@RestController
public class SingerController { 
    /**    
    * 添加@Valid 註解    
    * @param singer    
    * @return   
    */ 
    @PostMapping("/singer")    
    private String validator(@Valid @RequestBody Singer singer) {      
        System.out.print(singer);     
        return "ok"; 
}
{
    "fistName":null,
    "genre":"FEMALE"    
}
  • 返回結果

{
    "timestamp": "2020-01-11T15:16:22.851+0000",
    "status": 400,
    "error": "Bad Request",
    "errors": [
        {
            "codes": [
                "NotNull.singer.fistName",
                "NotNull.fistName",
                "NotNull.java.lang.String",
                "NotNull"
            ],
            "arguments": [
                {
                    "codes": [
                        "singer.fistName",
                        "fistName"
                    ],
                    "arguments": null,
                    "defaultMessage": "fistName",
                    "code": "fistName"
                }
            ],
            "defaultMessage": "名稱不能爲空",
            "objectName": "singer",
            "field": "fistName",
            "rejectedValue": null,
            "bindingFailure": false,
            "code": "NotNull"
        }
    ],
    "message": "Validation failed for object='singer'. Error count: 1",
    "path": "/singer"
}
  • 自定義返回結果

     入參的第二個地方,綁定BindingResult,當Bean中屬性不知足是,能夠獲取到註解上的信息,並放回到正則表達式

    自定義的結果中。spring

@PostMapping("/singer") 
private HttpResponse validator(@Valid @RequestBody Singer singer, BindingResult result) 
{   
    if (result.hasErrors()) {    
    return HttpResponse.error(result.getFieldError().getDefaultMessage());    
    }     return HttpResponse.ok();
    
}
  • 返回結果

{
    "code": 500,
    "message": "名稱不能爲空",
    "requestid": "eebb0bf86dc24aabb9051bf832542828"
}

4、建立自定義註解驗證器

 對於一些複雜的驗證,好比說手機號碼的驗證,須要多個條件,或者一個驗證的POJO中包含了另外一個類,出現了這樣的需求也是常有的,這就須要咱們自定義建立驗證器了,以手機的長度爲例,咱們自定義一個手機號的驗證。json

  • 建立自定義註解

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
@Documented
//使用的驗證器,自定義驗證器
@Constraint(validatedBy = PhoneValidator.class)
//註解的使用級別是方法、屬性上
@Target({ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Phone {  
    //若是 驗證通過PhoneValidator的驗證返回false ,則默認返回的信息  
    String message() default "長度必須大於11";   
    /**  
    *   
    * @return 
    */  
    Class<?>[] groups() default {};  
    Class<? extends Payload>[] payload() 
        default {}
    ;

}
  • 建立驗證器

package com.miroservice.chapter2.pojo;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
/** 
* 
自定義實現對phone的驗證邏輯
*/
public class PhoneValidator implements ConstraintValidator<Phone,String> {   
    /** 
    *  value就是屬性
    *   
    */ 
    @Override  
    public boolean isValid(String value, ConstraintValidatorContext context) { 
        if(value==null||value.trim().length()<12){       
            return false;   
        }else {         
            return true;     
        }   
    }
}
  • 對象添加手機號屬性並添加註解

public class Singer { 
    
@NotNull(message = "名稱不能爲空")  
@Size(min = 2, max = 5)  
    
private String fistName; 
    
private String lastName;  
@NotNull(message = "性別不能爲空") 
    
private Genre genre;   
    
@Phone()  
private String phone;
...
}
{
    "phone" : 1,
    "fistName": "zhang",
    "genre":"MALE"
}

 請求結果app

{
  "code": 500,
  "message": "長度必須大於11",
  "requestid": "38cc357c07144d098e7c5730cc8f4c08"
}

5、總結

 以上就是本期的分享,你還能夠關注本博客的#Spring Boot入門實踐系列!#框架

本文由博客一文多發平臺 OpenWrite 發佈!
個人博客[蘭陵笑笑生] ( http://www.hao127.com.cn/),歡...
相關文章
相關標籤/搜索