Bean Validation

    

   通过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>



AnnotationSupported data typesUse
@AssertFalseBoolean, booleanChecks that the annotated element is false
@AssertTrueBoolean, booleanChecks 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
@Futurejava.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 NumberChecks whether the annotated value is higher than or equal to the specified minimum
@NotNullAny typeChecks that the annotated value is not null.
@NullAny typeChecks that the annotated value is null
@Pastjava.util.Date,
java.util.Calendar;
Checks whether the annotated date is in the past
@Pattern(regex=,flag=)CharSequenceChecks if the annotated string matches the regular expression regex considering the given flag match
@Size(min=,max=)CharSequence,Collection,Map and arraysChecks if the annotated element's size is between min and max (inclusive)
@ValidAny non-primitive typePerforms 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;


@CreditCardNumberCharSequenceChecks that the annotated character sequence passes the Luhn checksum test. Note, this validation aims to check for user mistakes, not credit card validity!
@EmailCharSequenceChecks 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=)CharSequenceValidates that the annotated character sequence is between min and max included
@NotBlankCharSequence
@NotEmptyCharSequence,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 typesChecks 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;
          //...
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值