JSR303 verification usage and how to customize verification annotations

One, JSR303

JSR303 is a standard framework provided by Java for Bean data validity verification. It has been included in JavaEE6.0. JSR303 specifies verification rules by annotating standard annotations such as @NotNull @Max in Bean attributes and passes standard verification. The interface verifies the Bean.

2, JSR303 common annotations

td>

Annotation Function
@Null The annotated element must be null
@NotNull The annotated element must not be null
@NotBlank is used for String type parameter verification, checking that the string cannot be null and the size after trim()>0.
@NotEmpty The value of the annotated string must be non-empty
@AssortTrue The annotated element must be true
@AssortFalse The annotated element must be false
@Min(value) The annotated element must be a number, and its value must be less than or equal to the specified minimum value
@Max(value) The annotated element must be a number, and its value must be greater than or equal to the specified maximum value
@Size(max, min) The size of the annotated element must be within the specified range
@Digits(integer,fraction) Be The annotated element must be a number, and its value must be within the acceptable range
@Past The annotated element must be a past date
@Future The annotated element must be a future date
@Pattern(value) The annotated element must match the specified regular expression
@Email The annotated element must be an email address
@Length The size of the annotated string must be within the specified range
@ Range The annotated element must be within the appropriate range

3. How to use these annotations for verification

1. Introduction

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-validation -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
            <version>2.7.16</version>
        </dependency>

2. Mark annotations on the member attributes of the entity class

package com.wufeng.gulimall.product.entity;

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

import java.io.Serializable;
import java.util.Date;
import lombok.Data;
import org.hibernate.validator.constraints.URL;

import javax.validation.constraints.*;


@Data
@TableName("pms_brand")
public class BrandEntity implements Serializable {<!-- -->
private static final long serialVersionUID = 1L;

/**
* Brand id
*/
@TableId
private Long brandId;
/**
* Brand name
*/
@NotBlank(message = "Brand name must be submitted")
private String name;
/**
* Brand logo address
*/
@URL(message = "The logo must be an address in url format")
private String logo;
/**
\t * introduce
*/
private String descript;
/**
* Display status [0-not displayed; 1-display]
*/
private Integer showStatus;
/**
* Search initial letter
*/
@NotNull
@Pattern(regexp = "^[A-Za-z]$", message = "The first letter of the search must be a letter")
private String firstLetter;
/**
* Sort
*/
@NotNull
@Min(value = 0, message = "Sort must be greater than or equal to 0")
private Integer sort;

}

3. Add the @Valid annotation to the method in the Controller

 @RequestMapping("/save")
    public R save(@Valid @RequestBody BrandEntity brand/*, BindingResult result*/){<!-- -->

// //Data verification failed
// if (result.hasErrors()) {<!-- -->
// HashMap<String, String> map = new HashMap<>();
// //1. Get the error result of the verification
// result.getFieldErrors().forEach((item)->{<!-- -->
//
// //2. Get the wrong attribute name
// String field = item.getField();
// String message = item.getDefaultMessage();
// map.put(field,message);
//
// });
// return R.error(400,"The submitted data is illegal").put("data",map);
// }

brandService.save(brand);
        return R.ok();
    }

Four, group verification

1. Write a group identification interface

public interface AddGroup {<!-- -->
}
public interface UpdateGroup{<!-- -->
}

2. Add grouping attributes to the annotations in the entity class

package com.wufeng.gulimall.product.entity;

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

import java.io.Serializable;
import java.util.Date;

import com.wufeng.common.valid.AddGroup;
import com.wufeng.common.valid.UpdateGroup;
import lombok.Data;
import org.hibernate.validator.constraints.URL;

import javax.validation.constraints.*;

@Data
@TableName("pms_brand")
public class BrandEntity implements Serializable {<!-- -->
private static final long serialVersionUID = 1L;

/**
* Brand id
*/
@Null(message = "New brand id cannot be specified",groups = {<!-- -->UpdateGroup.class})
@NotNull(message = "Modification must specify the brand id", groups = {<!-- -->AddGroup.class})
@TableId
private Long brandId;
/**
* Brand name
*/
@NotBlank(message = "Brand name must be submitted", groups = {<!-- -->AddGroup.class,UpdateGroup.class})
private String name;
/**
* Brand logo address
*/
@URL(message = "The logo must be an address in url format")
private String logo;
/**
\t * introduce
*/
private String descript;
/**
* Display status [0-not displayed; 1-display]
*/
private Integer showStatus;
/**
* Search initial letter
*/
@NotNull
@Pattern(regexp = "^[A-Za-z]$", message = "The first letter of the search must be a letter")
private String firstLetter;
/**
* Sort
*/
@NotNull
@Min(value = 0, message = "Sort must be greater than or equal to 0")
private Integer sort;

}

3. Mark the @Validated annotation in the Controller method and add the used group

 @RequestMapping("/save")
    //@RequiresPermissions("product:brand:save")
    public R save(@Validated({<!-- -->AddGroup.class}) @RequestBody BrandEntity brand/*, BindingResult result*/){<!-- -->

// //Data verification failed
// if (result.hasErrors()) {<!-- -->
// HashMap<String, String> map = new HashMap<>();
// //1. Get the error result of the verification
// result.getFieldErrors().forEach((item)->{<!-- -->
//
// //2. Get the wrong attribute name
// String field = item.getField();
// String message = item.getDefaultMessage();
// map.put(field,message);
//
// });
// return R.error(400,"The submitted data is illegal").put("data",map);
// }

brandService.save(brand);
        return R.ok();
    }

At this time, if the save method is called, the member attributes of the BrandEntity entity marked with the AddGroup.class annotation will be verified. The verification annotation without the AddGroup.class attribute will not take effect.

5. Customized verification annotations

1. Write a custom verification annotation

@Constraint(
      validatedBy = {<!-- -->}
)
@Target({<!-- -->ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ListValue {<!-- -->

  //After the verification error, the message goes to the ValidationMessages.properties file to get the value com.wufeng.common.valid.ListValue.message
  String message() default "{com.wufeng.common.valid.ListValue.message}";

  //Support group verification
  Class<?>[] groups() default {<!-- -->};

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

  //Self-defined attributes
  int[] vals() default {<!-- -->};
}

2. Write a custom validator

//The ConstraintValidator interface must be implemented. The first generic is your verification annotation, and the second generic is the type of the attribute that needs to be verified.
public class ListValueConstraintValidator implements ConstraintValidator<ListValue,Integer> {<!-- -->

     private Set<Integer> set = new HashSet<>();
 
     //Initialization method, write your own logic
     @Override
     public void initialize(ListValue constraintAnnotation) {<!-- -->
     //Get the value of vals defined in the annotation and add it to the set
         int[] vals = constraintAnnotation.vals();
         for (int val : vals) {<!-- -->
             set.add(val);
         }
     }
 
     //Verification method, false verification information is wrong, write your own logic
     @Override
     public boolean isValid(Integer value, ConstraintValidatorContext constraintValidatorContext) {<!-- -->
     // Check whether the value is the value in the set, yes - true, no - false
         return set.contains(value);
     }
}

3. Associate the custom validator with the custom validation annotation, and associate the custom validator (there can be multiple) in the custom annotation

@Constraint(
 //Associated validator. The validator is ListValueConstraintValidator.class. Multiple validation classes can be written.
     validatedBy = {<!-- -->ListValueConstraintValidator.class}
)
@Target({<!-- -->ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ListValue {<!-- -->

     //After the verification error, the message goes to the ValidationMessages.properties file to get the value com.wufeng.common.valid.ListValue.message
     String message() default "{com.wufeng.common.valid.ListValue.message}";
 
     //Support group verification
     Class<?>[] groups() default {<!-- -->};
 
     Class<? extends Payload>[] payload() default {<!-- -->};
 
     //Self-defined attributes
     int[] vals() default {<!-- -->};
}

4. Configure message information in ValidationMessages.properties

You don’t need to configure this file, but you need to bring the message attribute when using annotations

com.wufeng.common.valid.ListValue.message=Must be a value within the specified range

5. Use custom annotations in the entity class (use this annotation on the attributes that need to be verified in the entity class)

 @ListValue(vals = {<!-- -->0,1},groups = {<!-- -->AddGroup.class})
  private Integer showStatus;

6. Test method

 /**
     * save
     */
    @RequestMapping("/save")
    public R save(@Validated({<!-- -->AddGroup.class}) @RequestBody BrandEntity brand){<!-- -->

brandService.save(brand);
        return R.ok();
    }

7. Test effect