通过Bean Validation 可以减少大量重复代码,可以很容通过注解配置约束,可以将约束与模型凝聚在一起。
依赖jar
<!-- bean validator --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.1.0.Final</version> </dependency> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>1.1.0.Final</version> </dependency>
Annotation | Supported data types | Use |
---|---|---|
@AssertFalse | Boolean, boolean | Checks that the annotated element is false |
@AssertTrue | Boolean, boolean | Checks that the annotated element is true |
@DecimalMax(value=,inclusive=) | BigDecimal,BigInteger,CharSequence, byte,short, int, long and the respective wrappers of the primitive types; | Checks whether the annotated value is less than the specified maximum, when inclusive=false. Otherwise whether the value is less than or equal to the specified maximum. The parameter value is the string representation of the max value according to the BigDecimal string representation. |
@DecimalMin(value=,inclusive=) | BigDecimal, BigInteger,CharSequence, byte,short, int, long and the respective wrappers of the primitive types; | Checks whether the annotated value is larger than the specified minimum, when inclusive=false. Otherwise whether the value is larger than or equal to the specified minimum. The parameter value is the string representation of the min value according to the BigDecimal string representation. |
@Digits(integer=,fraction=) | BigDecimal, BigInteger, CharSequence,byte,short, int, long and therespective wrappers of the primitive types; | Checks whether the annoted value is a number having up to integer digits and fraction fractional digits |
@Future | java.util.Date, java.util.Calendar; |
Checks whether the annotated date is in the future |
@Max(value=) | BigDecimal, BigInteger, byte, short, int,long and the respective wrappers of the primitive types;any sub-type of Number |
Checks whether the annotated value is less than or equal to the specified maximum |
@Min(value=) | BigDecimal,BigInteger,byte,short,int, long and the respective wrappers of the primitive types;, any sub-type of Number | Checks whether the annotated value is higher than or equal to the specified minimum |
@NotNull | Any type | Checks that the annotated value is not null. |
@Null | Any type | Checks that the annotated value is null |
@Past | java.util.Date, java.util.Calendar; |
Checks whether the annotated date is in the past |
@Pattern(regex=,flag=) | CharSequence | Checks if the annotated string matches the regular expression regex considering the given flag match |
@Size(min=,max=) | CharSequence,Collection,Map and arrays | Checks if the annotated element‘s size is between min and max (inclusive) |
@Valid | Any non-primitive type | Performs validation recursively on the associated object. If the object is a collection or an array, the elements are validated recursively. If the object is a map, the value elements are validated recursively. |
In addition to the constraints defined by the Bean Validation API Hibernate Validator provides several useful custom constraints which are listed in lower table;
@CreditCardNumber | CharSequence | Checks that the annotated character sequence passes the Luhn checksum test. Note, this validation aims to check for user mistakes, not credit card validity! |
CharSequence | Checks whether the specified character sequence is a valid email address. The optional parameters regexp and flags allow to specify an additional regular expression (including regular expression
flags)which the email must match. |
|
@Length(min=, max=) | CharSequence | Validates that the annotated character sequence is between min and max included |
@NotBlank | CharSequence | |
@NotEmpty | CharSequence,Collection,Map and arrays |
Checks whether the annotated element is not null nor empty |
@Range(min=,max=) | BigDecimal,BigInteger,CharSequence,byte,short, int, long and the respective wrappers of the primitive types | Checks whether the annotated value lies between (inclusive) the specified minimum and maximum |
@ScriptAssert(lang=, script=, alias=) |
Any type |
例子:属性校验
package org.hibernate.validator.referenceguide.chapter02.inheritance; public class Car { private String manufacturer; @NotNull public String getManufacturer() { return manufacturer; } //... }
package org.hibernate.validator.referenceguide.chapter02.inheritance; public class RentalCar extends Car { private String rentalStation; @NotNull public String getRentalStation() { return rentalStation;} }
ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); Validator validator = factory.getValidator();
Car car = new Car( null, true ); Set<ConstraintViolation<Car>> constraintViolations = validator.validate( car ); assertEquals( 1, constraintViolations.size() ); assertEquals( "may not be null", constraintViolations.iterator().next().getMessage() );
Car car = new Car( null, true ); Set<ConstraintViolation<Car>> constraintViolations = validator.validateProperty( car, "manufacturer" ); assertEquals( 1, constraintViolations.size() ); assertEquals( "may not be null", constraintViolations.iterator().next().getMessage() );
例子:方法参数校验
ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); executableValidator = factory.getValidator().forExecutables();
public class Car { public Car(@NotNull String manufacturer) { //... } @ValidRacingCar public Car(String manufacturer, String team) { //... } public void drive(@Max(75) int speedInMph) { //... } @Size(min = 1) public List<Passenger> getPassengers() { //... } }
Car object = new Car( "Morris" ); Method method = Car.class.getMethod( "drive", int.class ); Object[] parameterValues = { 80 }; Set<ConstraintViolation<Car>> violations = executableValidator.validateParameters( object, method, parameterValues ); assertEquals( 1, violations.size() ); Class<? extends Annotation> constraintType = violations.iterator() .next() .getConstraintDescriptor() .getAnnotation() .annotationType(); assertEquals( Max.class, constraintType );
Car object = new Car( "Morris" ); Method method = Car.class.getMethod( "getPassengers" ); Object returnValue = Collections.<Passenger>emptyList(); Set<ConstraintViolation<Car>> violations = executableValidator.validateReturnValue( object, method, returnValue ); assertEquals( 1, violations.size() ); Class<? extends Annotation> constraintType = violations.iterator() .next() .getConstraintDescriptor() .getAnnotation() .annotationType(); assertEquals( Size.class, constraintType );
Constructor<Car> constructor = Car.class.getConstructor( String.class ); Object[] parameterValues = { null }; Set<ConstraintViolation<Car>> violations = executableValidator.validateConstructorParameters( constructor, parameterValues ); assertEquals( 1, violations.size() ); Class<? extends Annotation> constraintType = violations.iterator() .next() .getConstraintDescriptor() .getAnnotation() .annotationType(); assertEquals( NotNull.class, constraintType );
//constructor for creating racing cars Constructor<Car> constructor = Car.class.getConstructor( String.class, String.class ); Car createdObject = new Car( "Morris", null ); Set<ConstraintViolation<Car>> violations = executableValidator.validateConstructorReturnValue( constructor, createdObject ); assertEquals( 1, violations.size() ); Class<? extends Annotation> constraintType = violations.iterator() .next() .getConstraintDescriptor() .getAnnotation() .annotationType(); assertEquals( ValidRacingCar.class, constraintType );
package org.hibernate.validator.referenceguide.chapter03.parameter; public class RentalStation { public RentalStation(@NotNull String name) { //... } public void rentCar( @NotNull Customer customer, @NotNull @Future Date startDate, @Min(1) int durationInDays) { //... } }
package org.hibernate.validator.referenceguide.chapter03.crossparameter.constrainttarget; public class Garage { @ELAssert(expression = "...", validationAppliesTo = ConstraintTarget.PARAMETERS) public Car buildCar(List<Part> parts) { //... } @ELAssert(expression = "...", validationAppliesTo = ConstraintTarget.RETURN_VALUE) public Car paintCar(int color) { //... } }
public class Car { @NotNull private String manufacturer; @Size(min = 2, max = 14, message = "The license plate must be between {min} and {max} characters long") private String licensePlate; @Min(value = 2, message = "There must be at least {value} seat${value > 1 ? ‘s‘ : ‘‘}") private int seatCount; @DecimalMax(value = "350", message = "The top speed ${formatter.format(‘%1$.2f‘, validatedValue)} is higher than {value}") private double topSpeed; @DecimalMax(value = "100000", message = "Price must not be higher than ${value}") private BigDecimal price; public Car(String manufacturer, String licensePlate, int seatCount, double topSpeed, BigDecimal price) { this.manufacturer = manufacturer; this.licensePlate = licensePlate; this.seatCount = seatCount; this.topSpeed = topSpeed; this.price = price; } // getters and setters ... }
Car car = new Car(null, "A", 1, 400.123456, BigDecimal.valueOf(200000)); String message = validator.validateProperty(car, "manufacturer") .iterator().next().getMessage(); assertEquals("may not be null", message); message = validator.validateProperty(car, "licensePlate").iterator() .next().getMessage(); assertEquals( "The license plate must be between 2 and 14 characters long", message); message = validator.validateProperty(car, "seatCount").iterator() .next().getMessage(); assertEquals("There must be at least 2 seats", message); message = validator.validateProperty(car, "topSpeed").iterator().next() .getMessage(); assertEquals("The top speed 400.12 is higher than 350", message); message = validator.validateProperty(car, "price").iterator().next() .getMessage(); assertEquals("Price must not be higher than $100000", message);
public enum CaseMode { UPPER, LOWER; }
@Target({ FIELD, METHOD, PARAMETER, ANNOTATION_TYPE }) @Retention(RUNTIME) @Constraint(validatedBy = CheckCaseValidator.class) @Documented public @interface CheckCase { String message() default "{org.hibernate.validator.referenceguide.chapter06.CheckCase." + "message}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; CaseMode value(); @Target({ FIELD, METHOD, PARAMETER, ANNOTATION_TYPE }) @Retention(RUNTIME) @Documented @interface List { CheckCase[] value(); } }
public class CheckCaseValidator implements ConstraintValidator<CheckCase, String> { private CaseMode caseMode; @Override public void initialize(CheckCase constraintAnnotation) { this.caseMode = constraintAnnotation.value(); } @Override public boolean isValid(String object, ConstraintValidatorContext constraintContext) { if (object == null) { return true; } if (caseMode == CaseMode.UPPER) { return object.equals(object.toUpperCase()); } else { return object.equals(object.toLowerCase()); } } }
public class Car { @NotNull private String manufacturer; @NotNull @Size(min = 2, max = 14) @CheckCase(CaseMode.UPPER) private String licensePlate; @Min(2) private int seatCount; public Car(String manufacturer, String licencePlate, int seatCount) { this.manufacturer = manufacturer; this.licensePlate = licencePlate; this.seatCount = seatCount; } // getters and setters ... }
// invalid license plate Car car = new Car("Morris", "dd-ab-123", 4); Set<ConstraintViolation<Car>> constraintViolations = validator .validate(car); assertEquals(1, constraintViolations.size()); assertEquals("Case mode must be UPPER.", constraintViolations .iterator().next().getMessage()); // valid license plate car = new Car("Morris", "DD-AB-123", 4); constraintViolations = validator.validate(car); assertEquals(0, constraintViolations.size());
@Target({ TYPE, ANNOTATION_TYPE }) @Retention(RUNTIME) @Constraint(validatedBy = { ValidPassengerCountValidator.class }) @Documented public @interface ValidPassengerCount { String message() default "{org.hibernate.validator.referenceguide.chapter06.classlevel." + "ValidPassengerCount.message}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
public class ValidPassengerCountValidator implements ConstraintValidator<ValidPassengerCount, Car> { @Override public void initialize(ValidPassengerCount constraintAnnotation) { } @Override public boolean isValid(Car car, ConstraintValidatorContext context) { if (car == null) { return true; } return car.getPassengers().size() <= car.getSeatCount(); } }
@NotNull @Size(min = 2, max = 14) @CheckCase(CaseMode.UPPER) @Target({ METHOD, FIELD, ANNOTATION_TYPE }) @Retention(RUNTIME) @Constraint(validatedBy = {}) @Documented public @interface ValidLicensePlate { String message() default "{org.hibernate.validator.referenceguide.chapter06." + "constraintcomposition.ValidLicensePlate.message}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
public class Car { @ValidLicensePlate private String licensePlate; //... }
Bean Validation,布布扣,bubuko.com
原文:http://blog.csdn.net/java_1111/article/details/22603731