1.目前springboot框架校验的注解也有不少,但是暂时没有发现一种字段校验是根据其他校验字段来做校验的;
比如纳税人为公司那么纳税号必须填写,纳税人是个人的话纳税号不用填写了。这种情况当然可以写个判断就行了,如果一个类或者多个类都这样那就得一行行的写校验了,写校验也是很耗时间的
其实这个可以统一做个注解来校验就OK了
所以这里也算个小需求吧,开始造轮子
方法:基于spring aspect切面来做的,具体看下面代码
/**
* 条件字段和值得关系
**/
public enum RelationEnums {
/**
* 相等
*/
EQ,
/**
* 小于
*/
LT,
/**
* 大于
*/
RT,
/**
* 包含
*/
CONTAINS,
;
RelationEnums(){}
}
/**
* 属性校验注解
*/
@Target({ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ConditionValid {
/**
* 字段关系枚举
*
*/
RelationEnums relation() default RelationEnums.EQ;
/**
*
* 默认是 字段依赖校验
*/
boolean isDependency() default true;
/**
* 条件字段
*
*/
String conditionFiled() default "";
/**
* 条件字段值
*
*/
String conditionValue() default "";
/**
* 需要检验的字段
*/
String field() default "";
/**
* 提示信息
*/
String message() default "";
/**
* 扩展
*/
@Target({ElementType.FIELD,ElementType.METHOD,ElementType.TYPE,ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@interface List{
ConditionValid[] values();
}
}
/**
* 复杂校验标识用于扫描,标注则标识启用上面的校验
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface ComplexValid {
}
/**
* 带标识注解的方法
*/
@ComplexValid
public Boolean addInvoiceHead(@Valid InvoiceHeadDTO invoiceHeadDTO) {
return invoiceHeadService.addOrUpdate(invoiceHeadDTO);
}
/**
*统一处理校验
*/
@Aspect
@Component
@Order(1)
public class ValidateAop {
/**
* 切面填充属性
* @param joinPoint 切点
* @param valid 属性
* @return obj
* @throws Throwable e
*/
@Around(value = "@annotation(valid)")
public Object validate(ProceedingJoinPoint joinPoint, ComplexValid valid) throws Throwable {
Object[] args = joinPoint.getArgs();
try {
Class<?> aClass = args[0].getClass();
ConditionValid.List annotation = aClass.getAnnotation(ConditionValid.List.class);
if(annotation!=null){
for (ConditionValid value : annotation.values()) {
Method method = aClass.getMethod(getMethodName(value.conditionFiled()));
Object invoke = method.invoke(args[0]);
Method t = aClass.getMethod(getMethodName(value.field()));
Object tv = t.invoke(args[0]);
String formatT = String.format(value.message(), value.conditionFiled(), value.conditionValue(), value.field());
if(value.relation()== RelationEnums.EQ&&value.conditionValue().equals(invoke.toString())&& ValidateUtils.isEmpty(tv)){
throw new RuntimeException(formatT);
}else if(value.relation()== RelationEnums.CONTAINS&&value.conditionValue().contains(invoke.toString())&&ValidateUtils.isEmpty(tv)){
throw new RuntimeException(formatT);
}
//todo 这里可以继续扩展的
}
}
return joinPoint.proceed();
} catch (Throwable e) {
e.printStackTrace();
throw e;
}
}
/**
* 用反射getXX方法,获取字段值
* @param field 字段
* @return String
*/
public static String getMethodName(String field){
String s = field.substring(0, 1).toUpperCase();
String end = field.substring(1);
return "get"+s+end;
}
}
这里举个例子:如果纳税人公司,那么纳税号不能为空
@ConditionValid.List(values =
{
@ConditionValid(conditionFiled = "headType", conditionValue = "0",relation = RelationEnums.CONTAINS,
field = "taxPlayerIdNum", message = "when %s = %s then %s is not empty")
}
)
public class InvoiceHeadDTO{
/**
* 纳税方
*/
@NotBlank(message = "taxPlayer is blank")
private String taxPlayer;
/**
* 抬头类型0:企业发票,1个人非企业
*/
private Integer headType;
/**
* 纳税人识别号
*/
private String taxPlayerIdNum;
}
上面也看到了NotBlank是框架有的,那么我们可以综合使用,还是挺好用的吧