/** * Bank card check */
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {StringChecker.class, ObjectChecker.class})
public @interface BankCard {

   String message(a) default"Incorrect format of bank card number"; Class<? >[] groups()default {};

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

   /** * ConstraintValidator * A So this class accepts only String arguments and Long arguments... * You can also write Object, so this class accepts all types of arguments, which can be distinguished by instanceof
   class StringChecker implements ConstraintValidator<BankCard.String> {
      /** * specifies the bank card number to validate the regular expression */
      private Pattern pattern = Pattern.compile("(^\d{19}$)");
      
      @Override
      public void initialize(BankCard constraintAnnotation) {
         // Initialize method
         System.out.println("StringChecker init");
      }

      @Override
      public boolean isValid(String value, ConstraintValidatorContext context) {
         // The logical method of validation; In this case, String value is the object that needs to be checked; it may be null;
         @notnull, @notblank, @notempty, etc
         if (StringUtils.isEmpty(value)) {
            return true;
         }
         Matcher matcher = pattern.matcher(value);
         // matches matches accurately
         returnmatcher.matches(); }}/ * * *@BankCardAnnotation annotation annotation field, because it is Object, so the received type is unlimited */
   class ObjectChecker implements ConstraintValidator<BankCard.Object> {

      @Override
      public void initialize(BankCard constraintAnnotation) {}@Override
      public boolean isValid(Object value, ConstraintValidatorContext context) {
         if (null == value) {
            return true;
         }
         
         // A value of type Object can receive data of any data type
         if (value instanceof String) {
            System.out.println("It is a String value:" + value);
         } else if (value instanceof Long) {
            System.out.println("It is of type Long:" + value);
         } / / and so on...
         
         return false; }}}Copy the code

In the custom validation annotation above, @constraint (validatedBy = stringChecker.class) validatedBy defines more than one line of code, enclosed by {}. In this line of code, the StringChecker class handles String logic

This inner class can be defined externally, for convenience

class StringChecker implements ConstraintValidator<BankCard.String> {}
Copy the code

With the @constraint annotation, the ConstraintValidator interface must be implemented

There are two generic types, the first is a custom annotation class, the second is the need to verify the data type, can use Object, indicating that all types are supported, according to different types of different logic method.

There are two methods in this interface, Initialize and isValid.

The first is to initialize the validator, and the result of initialization is called by isValid. The second is the validation logic, where the different logic methods are implemented. Return true, the validation passes, false fails, and the custom exception message inside message is thrown.

In addition:

This custom annotation logic handler class is managed as a bean by Spring by default because it implements the ConstraintValidator interface, so you can inject other services with @autoWiredu or @Resources in this logic handler class. And you don’t have to annotate spring beans with @compent on top of the class.

Custom validation type annotation class because it is used to validate data, generally added inside

String message() default “User does not exist or does not belong to the current organization “;

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

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

@Retention: Specifies the lifetime of the annotation class. It takes the following three parameters: retentionPolicy. SOURCE: Annotations are reserved only in the SOURCE file retentionPolicy. CLASS: Annotations remain in the class file and are discarded when loaded into the JVM VIRTUAL machine. @target: Indicates that the annotation can be declared before those elements. Elementtype. TYPE: Indicates that the annotation can only be declared before one class. Elementtype. FIELD: Indicates that the annotation can only be declared before a FIELD of a class. Elementtype. METHOD: Indicates that this annotation can only be declared before a METHOD of a class. Elementtype. PARAMETER: Indicates that this annotation can only be declared before a method PARAMETER. Elementtype. CONSTRUCTOR: Indicates that this annotation can only be declared before a class CONSTRUCTOR. Elementtype. LOCAL_VARIABLE: Indicates that this annotation can only be declared before a local variable. Elementtype. ANNOTATION_TYPE: Indicates that this annotation can only be declared before an annotation type. Elementtype. PACKAGE: Indicates that this annotation can only be declared before a PACKAGE name.Copy the code