some parameters that only one is not null valid

注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Documented
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomValid {

}

@Documented
@Constraint(validatedBy = OnlyOneNotNullValidator.class)
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface OnlyOneNotNull {

String message() default "only one filed should not be null";

Class<?>[] groups() default {};

Class<? extends Payload>[] payload() default {};

String[] fieldNames();

}

OnlyOneNotNullValidator.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
@Component
@Slf4j
public class OnlyOneNotNullValidator implements ConstraintValidator<OnlyOneNotNull, Object> {

private String[] fieldNames;

@Override
public void initialize(OnlyOneNotNull onlyOneNotNull) {
this.fieldNames = onlyOneNotNull.fieldNames();
}

@Override
public boolean isValid(Object object, ConstraintValidatorContext context) {
if (Objects.isNull(object)) {
return true;
}
Class clazz = object.getClass();
try {
List<Field> fields = Arrays.stream(fieldNames)
.map(fieldName -> ReflectionUtils.findField(clazz, fieldName))
.filter(Objects::nonNull).peek(field -> field.setAccessible(true))
.filter(field -> Objects.nonNull(ReflectionUtils.getField(field, object)))
.collect(Collectors.toList());

boolean onlyOneNotNull = fields.size() == 1;
if (!onlyOneNotNull) {
invalid(context);
} else if (fields.get(0).isAnnotationPresent(CustomValid.class)) {
validate(fields.get(0).get(object));
}
return onlyOneNotNull;
} catch (IllegalAccessException e) {
log.warn(e.getMessage(), e);
return false;
} catch (Exception e) {
return false;
}
}

private void invalid(ConstraintValidatorContext context) {
throw new RuntimeException(String.format("[%s]", String.join(", ", fieldNames)) + " only one filed should not be null");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// valid object's field, for example: valid ClassA.aaa  notNull.
public static void validate(Object object) {
if (object != null) {
Class objClass = object.getClass();
try {
object = objectMapper.readValue(objectMapper.writeValueAsString(object), Object.class);
XssUtils.unescapeObject(object);
object = objectMapper.convertValue(object, objClass);
} catch (IOException e) {
throw new RuntimeException("QUERY_PARAM_ERROR");
}
}
javax.validation.Validator validator = (javax.validation.Validator)new ApplicationContextHolder().context.getBean("validator");
Set<ConstraintViolation<Object>> violations = validator.validate(object);
if (!violations.isEmpty()) {
StringBuilder msg = new StringBuilder();
for (ConstraintViolation<Object> violation : violations) {
msg.append("[").append(violation.getPropertyPath()).append("]").append(violation.getMessage());
}
throw new RuntimeException("bad request");
}
}

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@OnlyOneNotNull(fieldNames = {"aClass", "bClass", "cClass"})
public class RequestDto {
@CustomValid
private AClass aClass;
@CustomValid
private BClass bClass;
@CustomValid
private CClass cClass;
}

@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AClass {
@NotNull
private Boolean aaa;

@NotNull
private BBBB bnbb;

@NotBlank
@Pattern(regexp = ApiGatewayConst.PatternRegexp.METHOD_HTTP_URL)
@Length(max = 1500)
private String url;

}

评论