java后台项目经常需要校对象的数据合法性,本文使用java反射与hibernate-validator注解的方式实现通用的对象合法性校验,包括对象中的集合属性中数据合法性校验,很有参考价值
默认项目为sprint boot,步骤如下:
1、添加hibernate-validator依赖
2、根据具体业务需要在Entity类的属性上添加需要的校验注解
3、对象数据保存前,调用公用的校验方法,方法使用反射与Validator结合的方式,返回校验有错误的信息(可以将该方法放置在AOP切面类中,实现更松耦合的校验与业务方法分离)
接着我们来看一下每一步骤的具体代码:
1、添加hibernate-validator依赖
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
2、根据具体业务需要在Entity类的属性上添加需要的校验注解
UserInfo ,UserOrderInfo,其中UserOrderInfo是UserInfo的属性值
@Data
@Table(name = "user_info")
public class UserInfo {
@Id
@Column(name = "id")
@GeneratedValue(generator = "JDBC")
@Comment(value = "数据库主键")
private Integer id;
/**用户编码*/
@Length(max = 32,message = "用户编码长度不可超过32位")
private String userCode;
private List<UserOrderInfo> userOrderInfoList;
}
@Data
@Table(name = "user_order_info")
public class UserOrderInfo {
@Id
@Column(name = "id")
@GeneratedValue(generator = "JDBC")
@Comment(value = "数据库主键")
private Integer id;
/**用户编码*/
@Length(max = 32,message = "用户编码长度不可超过32位")
private String userCode;
/**订单编码*/
@Length(max = 64,message = "订单编码长度不可超过64位")
private String orderCode;
/**商品名称*/
private String itemName;
//以下忽略订单中其他属性
}
3、对象数据保存前,调用公用的校验方法,方法使用反射与Validator结合的方式,返回校验有错误的信息(可以将该方法放置在AOP切面类中,实现更松耦合的校验与业务方法分离)
例如:this.validateEntity(userInfo);//userInfo中包含基本信息与用户所有订单信息,接下来看下具体校验代码
//该方法可校验系统中所有配置了hibernate-validator校验属性的对象,并返回所有校验失败的错误提示信息 private List<String> validateEntity(Object object){
// List<String> errorMessages = new ArrayList(); try { Set constraintViolations = validator.validate(object); Class<?> aClass = object.getClass(); Field[] declaredFields = aClass.getDeclaredFields(); //如果需要校验对象中存在集合或者对象属性,需要继续校验 for(Field field:declaredFields){ field.setAccessible(true); if(field.getGenericType() instanceof ParameterizedType){ ParameterizedType pt = (ParameterizedType) field.getGenericType(); //判断具体类的类型 if (pt.getRawType().equals(List.class)) { List objList = (List) field.get(object); for(Object curObj:objList){ Set constraintViolationsObj = validator.validate(curObj); constraintViolations.addAll(constraintViolationsObj); } } } } if (!constraintViolations.isEmpty()) { return this.extractMessage(constraintViolations); } } catch (ConstraintViolationException | IllegalAccessException | InstantiationException ex) { return errorMessages; } return errorMessages; } /** * 转换Set<ConstraintViolation>为List<message> */ protected List<String> extractMessage(Set<? extends ConstraintViolation> constraintViolations) { List<String> errorMessages = new ArrayList(); for (ConstraintViolation violation : constraintViolations) { errorMessages.add(violation.getMessage()); } return errorMessages; }
以上校验方法可通用,也可以写在AOP的切面类里,进行更优雅的数据合法性校验