1. 程式人生 > 程式設計 >JSR303校驗註解和自定義校驗註解的使用

JSR303校驗註解和自定義校驗註解的使用

引入validation依賴

 <!--JSR303依賴 -->
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-validation</artifactId>
 </dependency>

Null檢查
@Null(message = "") 驗證物件是否為null
@NotNull(message = "") 驗證物件是否不為null,無法查檢長度為0的字串
@NotBlank(message = "") 檢查約束字串是不是Null還有被Trim的長度是否大於0,只對字串,且會去掉前後空格.

@NotEmpty(message = "") 檢查約束元素是否為NULL或者是EMPTY.

Booelan檢查
@AssertTrue(message = "") 驗證 Boolean 物件是否為 true
@AssertFalse(message = "") 驗證 Boolean 物件是否為 false

長度檢查
@Size(min=,max=,message = "") 驗證物件(Array,Collection,Map,String)長度是否在給定的範圍之內
@Length(min=,message = "") Validates that the annotated string is between min and max included.

日期檢查
@Past(message = "") 驗證 Date 和 Calendar 物件是否在當前時間之前
@Future(message = "") 驗證 Date 和 Calendar 物件是否在當前時間之後
@Pattern(regexp = "",message = "") 驗證 String 物件是否符合正則表示式的規則

數值檢查

建議使用在包裝型別(Integer這類),不建議使用在int型別上,
因為表單值為“”時無法轉換為int,但可以轉換為Stirng為"",Integer為null
@Min(message = "") 驗證 Number 和 String 物件是否大等於指定的值

@Max(message = "") 驗證 Number 和 String 物件是否小等於指定的值
@DecimalMax(message = "") 值不大於約束中指定的最大值. 這個約束的引數是一個通過BigDecimal定義的最大值的字串表示.小數存在精度
@DecimalMin(message = "") 值必須不小於約束中指定的最小值. 這個約束的引數是一個通過BigDecimal定義的最小值的字串表示.小數存在精度
@Digits(message = "") 驗證 Number 和 String 的構成是否合法
@Digits(integer=,fraction=,message = "") 驗證字串是否是符合指定格式的數字,interger指定整數精度,fraction指定小數精度。
@Range(min=,message = "") 檢查數字是否介於min和max之間.
@Valid 遞迴的對關聯物件進行校驗,如果關聯物件是個集合或者陣列,那麼對其中的元素進行遞迴校驗,如果是一個map,則對其中的值部分進行校驗.(是否進行遞迴驗證)
@CreditCardNumber(message = "") 信用卡驗證
@Email(message = "") 驗證是否是郵件地址,如果為null,不進行驗證,算通過驗證。
@ScriptAssert(lang=,script=,alias=,message = "")
@URL(protocol=,host=,port=,regexp=,flags=,message = "")

每一個校驗註解都有一個message用來定義錯誤資訊的返回資訊,也有一個groups用來定義不同情形寫生效的註解,需要傳入一個介面型別的類用來定義。

在進行分組校驗的情況下,沒有攜帶groups的校驗註解不生效,不是一組的也不會生效,使用方式先在要校驗的欄位標記註解並且填入groups=介面名.class需要編寫一個空介面用來標記分組

不分組校驗的情況下不標記groups的註解也會生效

在springboot中使用@Validated(value = {介面名.class})來指定那個groups生效

自定義校驗可以使用@Pattern 輸入正則表示式,會根據正則校驗

在實體中新增校驗註解

前端將資料提交給後端的controller、controller通過對映將資料對映到實體,在對映的時候會進行校驗,如果校驗不通過會通過message填入的資訊將錯誤資訊返回給controller中對於的方法

在實體層添加註解,其中message是返回的訊息

public class Person {
 @NotEmpty(message="姓名不能為空")
 private String name;
 
 private int userId;
 
 @Length(min=6,max=10,message="密碼必須在6-10位之間")
 private String password;
 
 @Email(message="郵箱不符合格式")
 private String email;
}

開啟校驗

在入請求體引數加上@Valid註解

在springboot中使用@Validated註解,是JSR303規範中springboot的實現

@PostMapping("/person")
public Object addPerson(@RequestBody @Valid Person person,BindingResult result) {
 if (result.hasErrors()) { // 判斷異常,將異常返回
 List<ObjectError> allErrors = result.getAllErrors(); //獲取所有的異常資訊
 for (ObjectError error : allErrors) {
  System.out.println(error.getCode() + "\t"
   + error.getDefaultMessage());
 }
 }
 return person;
}

集中處理異常示例程式碼

import com.atguigu.common.exception.BizCodeEnume;
import com.atguigu.common.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.HashMap;
import java.util.Map;

/**
 * 集中處理所有異常
 */
@Slf4j
@RestControllerAdvice(basePackages = "拋異常的類全路徑")
public class GulimallExceptionControllerAdvice {


  @ExceptionHandler(value= MethodArgumentNotValidException.class)
  public R handleVaildException(MethodArgumentNotValidException e){
    log.error("資料校驗出現問題{},異常型別:{}",e.getMessage(),e.getClass());
    BindingResult bindingResult = e.getBindingResult();

    Map<String,String> errorMap = new HashMap<>();
    bindingResult.getFieldErrors().forEach((fieldError)->{
      errorMap.put(fieldError.getField(),fieldError.getDefaultMessage());
    });
    return R.error(BizCodeEnume.VAILD_EXCEPTION.getCode(),BizCodeEnume.VAILD_EXCEPTION.getMsg()).put("data",errorMap);
  }

  @ExceptionHandler(value = Throwable.class)
  public R handleException(Throwable throwable){

    log.error("錯誤:",throwable);
    return R.error(BizCodeEnume.UNKNOW_EXCEPTION.getCode(),BizCodeEnume.UNKNOW_EXCEPTION.getMsg());
  }
}

自定義校驗註解

自定義校驗註解必須要有三個內容values,message,groups

也就是必須要喲下面的3行程式碼

String message() default "{com.atguigu.common.valid.ListValue.message}";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };

message中{com.atguigu.common.valid.ListValue.message}是預設的返回錯誤資訊

因此需要建立對應的properties/yml檔案,並且在其中定義錯誤資訊的值

例如 com.atguigu.common.valid.ListValue.message=必須提交指定的值!

同時需要下面這些註解@Target指定註解在那些地方生效,METHOD表示方法、FIELD表示欄位其他的類推
@Constraint用來指定自定義校驗的校驗器,validatedBy = { ListValueConstraintValidator.class }表示指定ListValueConstraintValidator.class作為校驗器,可以有多個

@Documented
@Constraint(validatedBy = { ListValueConstraintValidator.class })
@Target({ METHOD,FIELD,ANNOTATION_TYPE,CONSTRUCTOR,PARAMETER,TYPE_USE })
@Retention(RUNTIME)

如果找不到類則新增依賴

<!-- https://mvnrepository.com/artifact/javax.validation/validation-api -->
<dependency>
  <groupId>javax.validation</groupId>
  <artifactId>validation-api</artifactId>
  <version>2.0.1.Final</version>
</dependency>

完整的自定義校驗註解的案例

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.ElementType.TYPE_USE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Documented
@Constraint(validatedBy = { ListValueConstraintValidator.class })
@Target({ METHOD,TYPE_USE })
@Retention(RUNTIME)
public @interface ListValue {
  String message() default "{com.atguigu.common.valid.ListValue.message}";

  Class<?>[] groups() default { };

  Class<? extends Payload>[] payload() default { };

  int[] vals() default { };
}

使用案例

groups指定分組生效

@ListValue(vals={0,1},groups = {AddGroup.class,UpdateStatusGroup.class})
private Integer showStatus;

要使校驗註解生效,需要有一個自定義的校驗註解器,實現ConstraintValidator介面需要有兩個泛型

第一個是註解類,另一個是校驗值的型別

例如

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.HashSet;
import java.util.Set;

public class ListValueConstraintValidator implements ConstraintValidator<ListValue,Integer> {

  private Set<Integer> set = new HashSet<>();
  //初始化方法
  @Override
  public void initialize(ListValue constraintAnnotation) {

    int[] vals = constraintAnnotation.vals();
    for (int val : vals) {
      set.add(val);
    }

  }

  //判斷是否校驗成功

  /**
   *
   * @param value 需要校驗的值
   * @param context
   * @return
   */
  @Override
  public boolean isValid(Integer value,ConstraintValidatorContext context) {

    return set.contains(value);
  }
}

進行校驗的類,其中BrandEntity 中有上面的showStatus欄位並且有對應的自定義校驗註解

  @RequestMapping("/update")
  public R update(@Validated(UpdateGroup.class) @RequestBody BrandEntity brand){
 /*業務程式碼*/
    return R.ok();
  }

到此這篇關於JSR303校驗註解和自定義校驗註解的使用的文章就介紹到這了,更多相關JSR303校驗註解內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!