Parameter validation in Java (non Spring version)

Keywords: Java Spring Mobile

1. Parameter validation in Java (non Spring version)

1.1. Preface

  • Why do I always encounter this kind of abnormal problem? We know that most of the time our parameter verification is carried out on the incoming parameters of the controller layer. Our common verification method is to introduce the following jar package, add @ Validated to the parameters, and make different comments on the parameters of the Bean object. You should be familiar with this common method of Spring.
  • But the requirement I meet now is that the boss pursues universality. There is only one controller entry, which is to distinguish which service to call through different tradecodes in the incoming parameters. At this time, I have to put the verification parameters on each specific service method. After my test, adding this annotation has no effect.
    <!--jsr 303-->
    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
        <version>1.1.0.Final</version>
    </dependency>
    @PostMapping("/save/valid")
    public RspDTO save(@RequestBody @Validated UserDTO userDTO) {
        userService.save(userDTO);
        return RspDTO.success();
    }
@Data
public class UserDTO implements Serializable {

    private static final long serialVersionUID = 1L;

    /*** User ID*/
    @NotNull(message = "user id Can not be empty")
    private Long userId;
    
    /** User name*/
    @NotBlank(message = "User name cannot be empty")
    @Length(max = 20, message = "User name cannot exceed 20 characters")
    @Pattern(regexp = "^[\\u4E00-\\u9FA5A-Za-z0-9\\*]*$", message = "User nickname limit: up to 20 characters, including text, letters and numbers")
    private String username;
    
    /** Cell-phone number*/
    @NotBlank(message = "Mobile number cannot be empty")
    @Pattern(regexp = "^[1][3,4,5,6,7,8,9][0-9]{9}$", message = "Wrong format of mobile number")
    private String mobile;

    /**Gender*/
    private String sex;

    /** mailbox*/
    @NotBlank(message = "Contact email cannot be empty")
    @Email(message = "Incorrect email format")
    private String email;

    /** Password*/
    private String password;

    /*** Creation time */
    @Future(message = "Time must be future time")
    private Date createTime;

}

1.2. scheme

  • We can't use its annotation, but we can use its method. Next, I wrote an example of using Java code to verify parameters. It can't be used directly in our own system. If you want to use it, please combine with your own system encapsulation method. I plan to make annotation form, use spring aop to cut my service layer, and the effect is similar to that of controller layer.

1.2.1. Main method

import org.springframework.validation.annotation.Validated;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.util.Date;
import java.util.Set;
import java.util.stream.Stream;

/**
 * @author laoliangliang
 * @date 2019/10/22 15:19
 */
public class ValidLearn {
    public static void main(String[] args) {
        ValidLearn learn = new ValidLearn();
        learn.testValid(new Order().setIdcard("33062119981012361X").setName("  ").setCreateDate(new Date()));
    }

    public void testValid(@Validated Order order) {
        ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
        Validator validator = validatorFactory.getValidator();
        //If the group Insert.class is empty, the id will not be checked.
        Set<ConstraintViolation<Order>> validate = validator.validate(order, Insert.class);
        Stream.of(validate).forEach(action -> {
            for (ConstraintViolation<Order> orderConstraintViolation : action) {
                String message = orderConstraintViolation.getMessage();
                System.out.println(message);
            }
        });
    }
}

1.2.2. Entity class

/**
 * @author laoliangliang
 * @date 2019/10/21 16:44
 */
@Data
@Accessors(chain = true)
public class Order {

    @NotNull(message = "id Can not be empty",groups = Update.class)
    private Long id;

    @NotEmpty(message = "name is not null",groups = Insert.class)
    private String name;

    @Future(message = "Time after must")
    private Date createDate;

    @IdCardValid(message = "idcard Wrongful")
    private String idcard;
}
  • The above two codes can verify the annotation of entity class object and print the message of failed verification. They can be modified to throw an exception if there is a verification error message.
  • The code also involves some details, such as group grouping and custom annotation.

1.2.3. group grouping

import javax.validation.groups.Default;

/**
 * @author laoliangliang
 * @date 2019/10/22 16:32
 */
public interface Update extends Default {
}
import javax.validation.groups.Default;

/**
 * @author laoliangliang
 * @date 2019/10/22 16:32
 */
public interface Insert extends Default {
}
  • In my example code, Insert.class is used, which means that when the insert action is performed, the annotation with this group will work. Therefore, if my ID is not passed, the annotation with id not empty will not work.

1.2.4. User defined notes

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author laoliangliang
 * @date 2019/10/22 15:55
 */
public class IdCardValidator implements ConstraintValidator<IdCardValid, Object> {

    private Pattern pattern = Pattern.compile("^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])" +
            "\\d{3}$|^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}([0-9]|X)$");
    @Override
    public void initialize(IdCardValid idCardValid) {
    }

    @Override
    public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {
        Matcher matcher = pattern.matcher(o.toString());
        return matcher.matches();
    }
}
/**
 * @author laoliangliang
 * @date 2019/10/22 15:53
 */
@Documented
@Target({ElementType.PARAMETER,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = IdCardValidator.class)
public @interface IdCardValid {

    String message() default "Illegal ID card";

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

    Class<? extends Payload>[] payload() default {};
}
  • In this case, I write a custom annotation to implement the ConstraintValidator interface. The annotation can be used by implementing the custom logic in isValid method.

1.3. summary

  • This article gives an example of Validation using Java code. It should verify the parameters of service layer. When it is applied to its own code, you can write a custom annotation to realize aop facet and verify in facet.

Posted by timbr8ks on Tue, 22 Oct 2019 04:02:19 -0700