一般将用于分组校验的interface和要验证的实体类分开,放到别的.java文件中。这么做可能是有些实体类比较相似,验证规则比较重复。因此单独将interface抽出来单独存放比较适合。
但是本人已经将实体类分别放在了pojo包下的base、vo、po、dto等六个包中,vo下的类又基本继承了base下的类。再建一个validation包来存储interface,新增了六个包,还要学pojo包一样分层。
最终的效果就像这样,未免让结构变得太过臃肿。
每次想要查看某实体类的校验规则就要去翻一遍。虽说这在某种程度上符合AOP思想,但controller和service都是有一定体量的,而只是存放一堆空空如也的接口名则显得意味不明。
众所周知,分组校验存在继承规则,像是public interface Group1 extends Default这种,子接口继承父接口的全部规则。那么,
经过试验后,本应用发现,分组校验与继承机制完全适配。
假设有A,B extends A,C extends A三个类。A中定义了a字段,B和C中都定义了b和c两个字段。
仅在A.java下定义public interface Group1,其他两个因为继承自A,不用显式定义。
对A类的a字段作非空校验。
@NotNull(message = "a can’t be null", groups = Group1.class)
private String a;
对B类的b字段作非空校验。
@NotNull(message = " b can’t be null ", groups = Group1.class)
private String b;
对C类的c字段作非空校验。
@NotNull(message = " b can’t be null ", groups = Group1.class)
private String b;
BController的insertB方法的入参里写上
insertB(@Validated(value=”B.Group”) @RequestBody B b)
使用postman发送请求,能够正常抛出a can’t be null和b can’t be null。
【将分组校验和类的继承结合起来做的好处】
1.不用建大量没有存储很多实质内容的接口包。
举例:购买电器时,该电器适合什么样的电压应该在附带的说明书里一并说清,而不是分开。所以分组所用的interface应该和类放在一起。
而要使用这个电器来煮饭、煮汤还是煮任何东西,则是个人的事情,你可能专门买一本食谱书再来管这件事。这就像controller和service,应该和实体类分开。
2.分组接口之间的继承关系和类的继承关系绑定,符合人的思维习惯。
@Data
public abstract class BaseEntity {
/**
* 示例属性。
*/
@NotNull(message = "1", groups = insertBaseEntity.class)
private String entity;
public interface insertBaseEntity{
};
}
@Data
public abstract class AbstractInformation extends BaseEntity {
/**
* 示例属性。
*/
@NotNull(message = "1", groups = insertAbstractInformation.class)
private String information;
public interface insertAbstractInformation extend insertBaseEntity{
};
}
举例:高级轿车继承自汽车。汽车不能没有轮子,高级轿车当然也不能没有轮子。
3.显著减少分组接口数量。
举例:“不能没有轮子”就是一组校验规则,你已经在汽车的说明文档里说过一次“不能没有轮子”了,不应该在高级轿车的说明文档里再说一次。反映到spring开发中,如果已经在BaseEntity定义了InsertBaseEntity,为什么还要在具体实体类B里定义一遍呢?如果这个实体类有特殊的地方,那就再单独写一个InsertA extends InsertBaseEntity即可。