feat: 增加唯一字段验证
This commit is contained in:
parent
66e19e81f7
commit
86714d7722
|
@ -0,0 +1,44 @@
|
||||||
|
package com.flyfish.framework.validation.annotations;
|
||||||
|
|
||||||
|
|
||||||
|
import com.flyfish.framework.validation.validators.IdCardValidator;
|
||||||
|
|
||||||
|
import javax.validation.Constraint;
|
||||||
|
import javax.validation.Payload;
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.Repeatable;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
import com.flyfish.framework.validation.annotations.UniqueField.List;
|
||||||
|
import com.flyfish.framework.validation.validators.UniqueFieldValidator;
|
||||||
|
|
||||||
|
import static java.lang.annotation.ElementType.*;
|
||||||
|
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
|
||||||
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
|
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
|
||||||
|
@Retention(RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@Constraint(validatedBy = {UniqueFieldValidator.class})
|
||||||
|
@Repeatable(List.class)
|
||||||
|
public @interface UniqueField {
|
||||||
|
|
||||||
|
String message() default "集合中的关键字段不唯一!";
|
||||||
|
|
||||||
|
// 唯一字段
|
||||||
|
String value();
|
||||||
|
|
||||||
|
//分组
|
||||||
|
Class<?>[] groups() default {};
|
||||||
|
|
||||||
|
//负载
|
||||||
|
Class<? extends Payload>[] payload() default {};
|
||||||
|
|
||||||
|
//指定多个时使用
|
||||||
|
@Target({FIELD, METHOD, PARAMETER, ANNOTATION_TYPE})
|
||||||
|
@Retention(RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@interface List {
|
||||||
|
UniqueField[] value();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
package com.flyfish.framework.validation.validators;
|
||||||
|
|
||||||
|
|
||||||
|
import com.flyfish.framework.validation.annotations.UniqueField;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import org.apache.commons.lang3.ClassUtils;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
|
||||||
|
import javax.validation.ConstraintValidator;
|
||||||
|
import javax.validation.ConstraintValidatorContext;
|
||||||
|
import java.beans.PropertyDescriptor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class UniqueFieldValidator implements ConstraintValidator<UniqueField, List<Object>> {
|
||||||
|
|
||||||
|
private String field;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(UniqueField uniqueField) {
|
||||||
|
this.field = uniqueField.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements the validation logic.
|
||||||
|
* The state of {@code value} must not be altered.
|
||||||
|
* <p>
|
||||||
|
* This method can be accessed concurrently, thread-safety must be ensured
|
||||||
|
* by the implementation.
|
||||||
|
*
|
||||||
|
* @param value object to validate
|
||||||
|
* @param context context in which the constraint is evaluated
|
||||||
|
* @return {@code false} if {@code value} does not pass the constraint
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isValid(List<Object> value, ConstraintValidatorContext context) {
|
||||||
|
int size = CollectionUtils.size(value);
|
||||||
|
if (size < 2) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
long count = value.stream().map(item -> {
|
||||||
|
if (item instanceof String || ClassUtils.isPrimitiveOrWrapper(item.getClass())) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
if (item instanceof Map) {
|
||||||
|
return ((Map<?, ?>) item).get(field);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
PropertyDescriptor descriptor = BeanUtils.getPropertyDescriptor(item.getClass(), field);
|
||||||
|
if (null != descriptor) {
|
||||||
|
return descriptor.getReadMethod().invoke(item);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} catch (IllegalAccessException | InvocationTargetException ignored) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}).distinct().count();
|
||||||
|
return count == size;
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import com.flyfish.framework.beans.meta.BeanPropertyType;
|
||||||
import com.flyfish.framework.beans.meta.BeanValidation;
|
import com.flyfish.framework.beans.meta.BeanValidation;
|
||||||
import com.flyfish.framework.validation.annotations.IdCard;
|
import com.flyfish.framework.validation.annotations.IdCard;
|
||||||
import com.flyfish.framework.validation.annotations.Phone;
|
import com.flyfish.framework.validation.annotations.Phone;
|
||||||
|
import com.flyfish.framework.validation.annotations.UniqueField;
|
||||||
import com.flyfish.framework.validation.enums.PhoneType;
|
import com.flyfish.framework.validation.enums.PhoneType;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.hibernate.validator.constraints.Currency;
|
import org.hibernate.validator.constraints.Currency;
|
||||||
|
@ -67,10 +68,13 @@ public enum ValidationCandidate {
|
||||||
// 货币
|
// 货币
|
||||||
CURRENCY((annotation, validation) -> validation.setValidator("currency"), Currency.class),
|
CURRENCY((annotation, validation) -> validation.setValidator("currency"), Currency.class),
|
||||||
// 手机号
|
// 手机号
|
||||||
PHONE(((annotation, validation) -> validation.setValidator("phone").prop("type",
|
PHONE((annotation, validation) -> validation.setValidator("phone").prop("type",
|
||||||
annotation.getEnum("type", PhoneType.class).name().toLowerCase())), Phone.class),
|
annotation.getEnum("type", PhoneType.class).name().toLowerCase()), Phone.class),
|
||||||
// 身份证号
|
// 身份证号
|
||||||
ID_CARD(((annotation, validation) -> validation.setValidator("idCard")), IdCard.class);
|
ID_CARD((annotation, validation) -> validation.setValidator("idCard"), IdCard.class),
|
||||||
|
// 唯一字段
|
||||||
|
UNIQUE_FIELD((annotation, validation) -> validation.setValidator("uniqueField")
|
||||||
|
.prop("field", annotation.getString("value")), UniqueField.class);
|
||||||
|
|
||||||
private final BiConsumer<MergedAnnotation<?>, BeanValidation> mapper;
|
private final BiConsumer<MergedAnnotation<?>, BeanValidation> mapper;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue