一.校验组序列
默认情况下,约束的验证是没有一定的顺序的,不管他们是属于哪个认证组的.但是在有些环境中,我们控制这些约束验证的顺序还是很有用的.
就拿我们上一个例子来说,我们可以这样:首先在我们检查车的性能之前关于车的默认的约束应该是验证通过的,然后,在我们行驶之前,我们应该检查驾驶员的相关约束条件.为了实现这样的认证顺序,我们要定义一个新的接口,在这个接口上面加上一个@GroupSequence 注释,用来定义我们验证组执行的顺序
注意:验证组中如果有一个约束失败了,那么后面的约束将都会认为是失败的.
如下:
@GroupSequence({Default.class, CarChecks.class, DriverChecks.class}) public interface OrderedChecks { }
警告
一个校验组序列中包含的校验组和这个校验组序列不能造成直接或者间接的循环
引用. 包括校验组继承. 如果造成了循环引用的话, 会导
致 GroupDefinitionException 异常.
定义好了之后,就来使用:
@Test public void testOrderedChecks() { Car car = new Car( "Morris", "DD-AB-123", 2 ); car.setPassedVehicleInspection( true ); Driver john = new Driver( "John Doe" ); john.setAge( 18 ); john.passedDrivingTest( true ); car.setDriver( john ); assertEquals( 0, validator.validate( car, OrderedChecks.class ).size() ); }
二.对一个类重定义其默认校验组
这个@GroupSequence的注释还有第二种作用,它可以用来让你重新定义一个类的默认组的方法.为了重新定义类.我们只需要在这个类上加一个@GroupSequence注解
这个注解中定义的组的组序列将会替代这个类的默认的.
例:
第一步.先来一个出租车的认证组
package test01; /** * @author Administrator *出租车认证组 */ public interface RentalChecks { }
2.再来一个出租车类
package test01; import javax.validation.GroupSequence; import javax.validation.constraints.AssertFalse; @GroupSequence({ RentalChecks.class, CarChecks.class, RentalCar.class }) public class RentalCar extends Car { /** * 是否已经出租 */ @AssertFalse(message = "The car is currently rented out", groups = RentalChecks.class) private boolean rented; public RentalCar(String manufacturer, String licencePlate, int seatCount) { super(manufacturer, licencePlate, seatCount); } public boolean isRented() { return rented; } public void setRented(boolean rented) { this.rented = rented; } }
注意:由于在认证组中不能有循环依赖且当给一个类重新定义组序列时认证组序列中不能加入默认(Default)组,所以我们需要将这个类本身添加进去,如上例!
3.最后进行测试
@Test
public void carIsRented() {
RentalCar rentalCar = new RentalCar("Morris", "DD-AB-123", 2);
rentalCar.setPassedVehicleInspection(true);
rentalCar.setRented(true);
Set<ConstraintViolation<RentalCar>> constraintViolations = validator.validate(rentalCar);
assertEquals(1, constraintViolations.size());
assertEquals("Wrong message", "The car is currently rented out",
constraintViolations.iterator().next().getMessage());
rentalCar.setRented(false);
constraintViolations = validator.validate(rentalCar);
assertEquals(0, constraintViolations.size());
}
注意:
当在一个类上加@GroupSequence时,它是不会传递到相关的对象中,这意味着如果你在上面的例子中添加了DriverChecks 是没有效果的.只有当认证一个实例的时候,才会有效果
三.@GroupSequenceProvider
关于前面的@javax.validation.GroupSequence 注解是一个标准的Bean认证注解,正如前面所见的它能够让你静态的重新定义一个类的默认认证组的组顺序,Hibernate Validator同时也提供了一个可以自己操作的,非标准的注解org.hibernate.validator.group.GroupSequenceProvider,它能够让你动态的重新定义一个组的顺序.
1.先创建一个GroupSequenceProvider用来动态选择认证组
public class RentalCarGroupSequenceProvider implements DefaultGroupSequenceProvider<RentalCar> { public List<Class<?>> getValidationGroups(RentalCar car) { List<Class<?>> defaultGroupSequence = new ArrayList<Class<?>>(); defaultGroupSequence.add( RentalCar.class ); if ( car != null && !car.isRented() ) { defaultGroupSequence.add( CarChecks.class ); } return defaultGroupSequence; } }
2.使用这个GroupSequenceProvider
@GroupSequenceProvider(RentalCarGroupSequenceProvider.class) public class RentalCar extends Car { @AssertFalse(message = "The car is currently rented out", groups = RentalChecks.class) private boolean rented; public RentalCar(String manufacturer, String licencePlate, int seatCount) { super( manufacturer, licencePlate, seatCount ); } public boolean isRented() { return rented; } public void setRented(boolean rented) { this.rented = rented; }