自定義校驗註解(controller、method、(groups)分組的用法)

1、首先創建兩個自定義校驗註解類

package com.example.demo.annotation;

import com.example.demo.interface2.CreateAction;

import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;

import java.lang.annotation.*;

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

/**
 * 自定義校驗註解
 */
@Constraint(validatedBy = {Name.NameUtil.class})
@Documented
@Retention(RUNTIME)
@Target({ElementType.ANNOTATION_TYPE, METHOD, ElementType.FIELD})
public @interface Name {

//     真坑,以下三個參數的名稱必須爲這三個,不能爲其他
    String message() default "姓名必須爲小黑";

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

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

    @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
    @Retention(RUNTIME)
    @Documented
    @interface List{
        Name [] value();
    }

    class NameUtil implements ConstraintValidator<Name,String>, CreateAction {

        @Override
        public void initialize(Name constraintAnnotation) {
//        TODO 可以用以初始化數據
        }

        @Override
        public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
            if("小黑".equals(s)){
                return true;
            }else{
                return false;
            }

        }

    }
}

package com.example.demo.annotation;

import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;
import java.lang.annotation.*;

/**
 * 自定義校驗註解
 */
@Constraint(validatedBy = {Sex.SexUtil.class})
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
public @interface Sex {

    //     真坑,以下三個參數的名稱必須爲這三個,不能爲其他
    String message() default "性別必須爲女";

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

    Class<? extends Payload>[] payload() default {};
    class SexUtil implements ConstraintValidator<Sex, Object> {

        @Override
        public void initialize(Sex constraintAnnotation) {
//        TODO 可以用以初始化數據
        }

        @Override
        public boolean isValid(Object s, ConstraintValidatorContext constraintValidatorContext) {

//            System.out.println(s.toString());
//            System.out.println(s.getClass().getName());
            if("女".equals(s)){
                return true;
            }else{
                return false;
            }
        }
    }
}

  

 

package com.example.demo.entity;

import com.example.demo.annotation.Name;
import com.example.demo.annotation.Sex;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.validation.constraints.NotNull;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Sex(message = "性別必須爲女2")
public class E {
    private int id;
    @Name(message = "姓名必須爲小黑2")
    @NotNull
    private String name;
    private String age;
    @NotNull
    private String sex;
}

2、校驗註解的使用

1>、controller中的使用

    @RequestMapping(value = "/pAnnotation",method = RequestMethod.GET,produces = "application/json;charset=UTF-8")
    @ApiOperation(value = "測試自定義校驗註解controller層")
    public void pAnnotation(@Valid E e ,BindingResult bindingResult){
        p1.pAnnotation(e,bindingResult);
    }
   public void pAnnotation(E e , BindingResult bindingResult) {
        if (bindingResult.hasErrors()){
            bindingResult.getAllErrors().forEach(s-> {
                System.out.println(s.getDefaultMessage());
            });
        }else{
            System.out.println("沒有報錯");
        }
    }

2>、方法中觸發註解

package com.example.demo.util;

import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.Set;

@Component
public class AnnotationCheck<T> {

    private static Validator validator = Validation.buildDefaultValidatorFactory().getValidator();

    public void checkAnnotation(T t){

            //執行驗證
            Set<ConstraintViolation<T>> constraintViolations = validator.validate(t);
            //打印校驗信息
            if (!CollectionUtils.isEmpty(constraintViolations)) {
                for (ConstraintViolation<T> constraintViolation : constraintViolations) {
                    System.out.println(constraintViolation.getPropertyPath().toString() + ": " + constraintViolation.getMessage());
                }
            }
    }

}

 調用:

 annotationCheck.checkAnnotation(e);

3>分組的使用

定義兩個空接口,分別代表E對象的增加校驗規則和修改校驗規則

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

修改實體中的註解

package com.example.demo.entity;

import com.example.demo.annotation.Name;
import com.example.demo.annotation.Sex;
import com.example.demo.interface2.CreateAction;
import com.example.demo.interface2.UpdateAction;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.validation.constraints.NotNull;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Sex(message = "性別必須爲女2")
public class E {
    private int id;
    @Name.List({
            @Name(groups = CreateAction.class ,message = "創建時姓名必須爲小黑2"),
            @Name(groups = UpdateAction.class ,message = "修改時姓名必須爲小黑2")
    })
    @NotNull
    private String name;
    private String age;
    @NotNull
    private String sex;
}

使用:

 @RequestMapping(value = "/pAnnotation3",method = RequestMethod.GET,produces = "application/json;charset=UTF-8")
    @ApiOperation(value = "測試自定義校驗註解-groups分組")
    public void pAnnotation3( @Validated({CreateAction.class}) E e,BindingResult bindingResult){
        if (bindingResult.hasErrors()){
            bindingResult.getAllErrors().forEach(s-> {
                System.out.println(s.getDefaultMessage());
            });
        }else{
            System.out.println("沒有報錯");
        }
    }

結果

創建時姓名必須爲小黑2

此時只會對標註了‘CreateAction.classd的註解生效,

分組用在方法上---待實現

註解用在方法上

1、實例化MethodValidationPostProcessor

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


 

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

@RestController
@Validated
public class ValidateController {
}

 

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

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

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

{
  "timestamp": "2020-05-07T11:51:00.141+0000",
  "status": 500,
  "error": "Internal Server Error",
  "message": "An Errors/BindingResult argument is expected to be declared immediately after the model attribute, the @RequestBody or the @RequestPart arguments to which they apply: public void com.example.demo.controller.PracticeController.pAnnotation4(java.lang.String,org.springframework.validation.BindingResult)",
  "path": "/practice/pAnnotation4"
}

自定義註解是BindException錯誤,其他組件的註解是ConstraintViolationException

想辦法集中處理TODO

 

--TODO 待實現,使用攔截器攔截並返回業務錯誤---

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

@AssertFalse 驗證註解的元素值是false
@AssertTrue 驗證註解的元素值是true
@DecimalMax(value=x) 驗證註解的元素值小於等於@ DecimalMax指定的value值
@DecimalMin(value=x) 驗證註解的元素值小於等於@ DecimalMin指定的value值
@Digits(integer=整數位數, fraction=小數位數) 驗證註解的元素值的整數位數和小數位數上限
@Future 驗證註解的元素值(日期類型)比當前時間晚
@Max(value=x) 驗證註解的元素值小於等於@Max指定的value值
@Min(value=x) 驗證註解的元素值大於等於@Min指定的value值
@NotNull 驗證註解的元素值不是null
@Null 驗證註解的元素值是null
@Past 驗證註解的元素值(日期類型)比當前時間早
@Pattern(regex=正則表達式, flag=) 驗證註解的元素值與指定的正則表達式匹配
@Size(min=最小值, max=最大值) 驗證註解的元素值的在min和max(包含)指定區間之內,如字符長度、集合大小
@Valid 驗證關聯的對象,如賬戶對象裏有一個訂單對象,指定驗證訂單對象
@NotEmpty 驗證註解的元素值不爲null且不爲空(字符串長度不爲0、集合大小不爲0)
@Range(min=最小值, max=最大值) 驗證註解的元素值在最小值和最大值之間
@NotBlank 驗證註解的元素值不爲空(不爲null、去除首位空格後長度爲0),不同於@NotEmpty,@NotBlank只應用於字符串且在比較時會去除字符串的空格
@Length(min=下限, max=上限) 驗證註解的元素值長度在min和max區間內
@Email 驗證註解的元素值是Email,也可以通過正則表達式和flag指定自定義的email格式

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章