Hibernate Validator Practice One of the introductory articles

Source: Internet
Author: User

In the business logic in the background, the checksum of the data value exists in each layer (presentation layer, business layer, data access layer, etc.), and the rules of each layer check are different, as shown in

Note: This image is from Hibernate Validator official website

The repeated checksum logic in each layer leads to unnecessary resource consumption and makes logic less than single (each layer is mixed with a checksum logic), and the JSR 303 Bean validation is a data-validated Java EE specification generated in this context. The Hibernate validator we will introduce in this article is a good practice for the JBoss Community Open Source, a JSR 303 Bean validation specification.

Note: This image is from Hibernate Validator official website

Here's a concrete list of how to use Hibernate Validator in our projects

First we define a struct person, specifically defined as follows
public class Person {
@NotNull
private String name;
@Min(value = 1)
private int age;
@NotNull(groups = Intf1.class)
@Size(min = 1, max = 3, groups = Intf2.class)
private String group;
@GenderCase(value = GenderType.FEMALE)
private GenderType gender;
@Max(100)
public int getAge() {
return age;
}
@Max(50)
public int getAgeOther() {
return age + 2;
}
@Max(50)
public int getAgeOther(int num) {
return 51;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}

The use of max,min,notnull,size in this class is the constraints built into JSR 303 (constraint), gendercase is a custom constraint, which is described later.

To constrain the bean, first we need to get a validator instance
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();

(a) How to verify the constraints built into the JSR 303
Based on the definition of the person struct above, let's look at a simple example
Person person = new Person(null, 20);
Set<ConstraintViolation<Person>> constraintViolations = validator.validate(person);
assertEquals(1, constraintViolations.size());
System.out.println(constraintViolations);

In the person struct definition, name is NOT NULL, here we deliberately construct a null person instance of name, and the result in console input is as follows:

[constraintviolationimpl{interpolatedmessage= ' cannot be null ', Propertypath=name, Rootbeanclass=class Hibernate.validator.Person, messagetemplate= ' {javax.validation.constraints.NotNull.message} '}]

As can be seen from the example above, it is only required to add the built-in constraint annotations of JSR 303 to the corresponding properties in the definition structure, through the Validate method of the validator instance, if the returned set collection is not empty, the values of which properties are known to be illegal by traversing the collection.

Constraint in Bean Validation
Table 1. Built-in constraint in Bean Validation
@Null The annotated element must be Null
@NotNull annotated element must not be null
@AssertTrue The annotated element must be true
@AssertFalse The annotated element must be false
@Min (value) The annotated element must be a number whose value must be greater than or equal to the specified minimum value
@Max (value) The annotated element must be a number whose value must be less than or equal to the specified maximum value
@DecimalMin (value) The annotated element must be a number whose value must be greater than or equal to the specified minimum value
@DecimalMax (value) The annotated element must be a number whose value must be less 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) The annotated element must be a number whose value must be within an 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 conform to the specified regular expression
Table 2. Hibernate Validator Additional constraint
@Email The annotated element must be an e-mail address
@Length the size of the annotated string must be within the specified range
@NotEmpty The annotated string must be non-empty
@Range The annotated element must be within the appropriate range

Note: The contents of the above two tables are from here,
If you have a struct nested, you only need to pass valid annotations on the composite attribute, you can check recursively.

(ii) Validatevalue and Validateproperty
Through the definition of Javax.validation.Validator interface class, there are three methods of calibration, namely Validate,validateproperty,validatevalue. Where validate checks all attributes, and Validateproperty is checked against a specific property, Validatevalue is the validation of a specific property and a specific value. See the following two examples

A first example:

Person person = new Person(null, 101);
Set<ConstraintViolation<Person>> constraintViolations = validator.validateProperty(person, "age");
assertEquals(1, constraintViolations.size());
System.out.println(constraintViolations);

According to the structure definition above, we can see that there are two constraints on age in the person structure, one is the minimum value of 1, the other is the constraint on the getter method can not exceed 100, the result of executing the above logical output is:

[constraintviolationimpl{interpolatedmessage= ' Max cannot exceed ', Propertypath=age, Rootbeanclass=class Hibernate.validator.Person, messagetemplate= ' {javax.validation.constraints.Max.message} '}]

Visible Validateproperty not only validates the value of field, but also verifies the Getter method.

A second example:

Set<ConstraintViolation<Person>> constraintViolations = validator.validateValue(Person.class, "name", null);
assertEquals(1, constraintViolations.size());
System.out.println(constraintViolations);

The second example shows that when executing validatevalue, given a struct definition, field name to see if that particular value conforms to the constraint, the result of execution is as follows:

[constraintviolationimpl{interpolatedmessage= ' cannot be null ', Propertypath=name, Rootbeanclass=class Hibernate.validator.Person, messagetemplate= ' {javax.validation.constraints.NotNull.message} '}]

(iii) Grouping of constraints
The concept of group is defined in JSR 303, identified by the defined interface class, and can be seen in the example of the person struct definition above with a group attribute with two constraints, @notnull (groups = Intf1.class) and @size (min = 1, max = 3, groups = Intf2.class)

Here's how to group in the parameter check with the result of a piece of code execution

Set<ConstraintViolation<Person>> constraintViolations = validator.validateValue(Person.class, "group", null, Intf1.class);
assertEquals(1, constraintViolations.size());
System.out.println("validate Intf1 |" + constraintViolations);
constraintViolations = validator.validateValue(Person.class, "group",null, Intf2.class);
assertEquals(0, constraintViolations.size());
System.out.println("validate Intf2 |" + constraintViolations);
constraintViolations = validator.validateValue(Person.class, "group","test", Intf2.class, Intf1.class);
assertEquals(1, constraintViolations.size());
System.out.println("validate Intf1&Intf2 |" + constraintViolations);

Upper segment logic when the group value is null, the first is checked with the constraint condition identified by the INTF1, and is verified by the constraint with the INTF2 identity. When the group value is test, it is also checked with the constraints identified by the INTF1 and INTF2. The results of the implementation are as follows:

Validate INTF1 | [constraintviolationimpl{interpolatedmessage= ' cannot be null ', Propertypath=group, Rootbeanclass=class Hibernate.validator.Person, messagetemplate= ' {javax.validation.constraints.NotNull.message} '}]
Validate INTF2 | []
Validate INTF1&INTF2 | [constraintviolationimpl{interpolatedmessage= ' number must be between 1 and 3 ', Propertypath=group, Rootbeanclass=class Hibernate.validator.Person, messagetemplate= ' {javax.validation.constraints.Size.message} '}]

As can be seen from the above example, different calibration rules can be selected according to the specific business.

(iv) Customization of constraints
Customizing the constraints requires two steps, and the first step is to define the constraint's annotation class:

@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = GenderTypeValidator.class)
public @interface GenderCase {
String message() default "genderType invalid";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
GenderType value() default GenderType.FEMALE;
}

There are three points to be concerned about here, the first one is @constraint (Validatedby = gendertypevalidator.class) Here you specify the implementation class for the constraint check below, and the second is the message property, Illegal for checksum is the default message template, and the third one is the constraint value for the annotation. In this example, the constraint value of the annotation is represented by an enumeration value of male/female, the default value is female

The second step is to implement the Javax.validation.constraintvalidator<a extends Annotation, t> interface of the constraint check implementation class, the above said Validatedby point is the implementation class, Where a represents a custom annotation class, T represents the type of field to validate. The specific logic is set out below:

public class GenderTypeValidator implements
ConstraintValidator<GenderCase, GenderType> {
GenderType value;
@Override
public void initialize(GenderCase constraintAnnotation) {
value = constraintAnnotation.value();
}
@Override
public boolean isValid(GenderType obj, ConstraintValidatorContext context) {
if (value != null && obj != null && value != obj) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate("gender should be " + value + "| the value is " + obj).addConstraintViolation();
return false;
} else {
return true;
}
}
}

The constraint of the annotation is obtained in the initialization method, and the value of obj passed in the IsValid method is compared with the constraint, and if satisfied returns true to indicate that the checksum is passed, and false if not satisfied. The error information is stored on the context Constraintvalidatorcontext and is eventually fed back to the caller.

The following is the logic that invokes the custom constraint:

Set<ConstraintViolation<Person>> constraintViolations = validator.validateValue(Person.class, "gender", GenderType.MALE);
assertEquals(1, constraintViolations.size());
System.out.println(constraintViolations);

The results of the implementation are as follows:

[constraintviolationimpl{interpolatedmessage= ' Gender should be female| the value is MALE ', Propertypath=gender, Rootbeanclass=class Hibernate.validator.Person, messagetemplate= ' gender should be female| The value is MALE '}]

Hibernate Validator Practice One of the introductory articles

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.