3 回答

TA貢獻(xiàn)1784條經(jīng)驗 獲得超2個贊
我假設(shè)username OR email不能為空。不是異或。
在類中添加這個 getter User:
@AssertTrue(message = "username or email is required")
private boolean isUsernameOrEmailExists() {
return username != null || email != null;
}
根據(jù)我的經(jīng)驗,方法名稱必須遵循 getter 名稱約定,否則這將不起作用。例如,getFoo或isBar。
這有一個小問題:此驗證錯誤的字段名稱將是usernameOrEmailExists,只有 1 個錯誤字段。如果這不是問題,這可能會有所幫助。
但是,如果您想在發(fā)生錯誤時擁有username和email字段,則可以使用此解決方法:
public String getUsername() {
return username;
}
public String getEmail() {
return email;
}
@AssertTrue(message = "username or email is required")
private boolean isUsername() {
return isUsernameOrEmailExists();
}
@AssertTrue(message = "username or email is required")
private boolean isEmail() {
return isUsernameOrEmailExists();
}
private boolean isUsernameOrEmailExists() {
return username != null || email != null;
}
get...方法只是一般用途的簡單吸氣劑,is... 用于驗證。這將發(fā)出 2 個帶有username和email字段的驗證錯誤。

TA貢獻(xiàn)1851條經(jīng)驗 獲得超3個贊
我會嘗試為您實現(xiàn)它(即使我沒有 IDE)。
在里面ConstraintValidator#initialize你可以得到配置字段的名稱,這些名稱不能是null.
@Override
public void initialize(final CombinedNotNull combinedNotNull) {
fields = combinedNotNull.fields();
}
在里面ConstraintValidator#isValid,您可以使用這些字段的名稱來檢查Object字段。
@Override
public boolean isValid(final Object value, final ConstraintValidatorContext context) {
final BeanWrapperImpl beanWrapper = new BeanWrapperImpl(value);
for (final String f : fields) {
final Object fieldValue = beanWrapper.getPropertyValue(f);
if (fieldValue == null) {
return false;
}
}
return true;
}
注解:
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Retention(RUNTIME)
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Constraint(validatedBy = CombinedNotNullValidator.class)
public @interface CombinedNotNull {
String message() default "username or email is required";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
/**
* Fields to validate against null.
*/
String[] fields() default {};
}
注釋可以應(yīng)用為
@CombinedNotNull(fields = {
"fieldName1",
"fieldName2"
})
public class MyClassToValidate { ... }
要了解如何創(chuàng)建類級約束注釋,請始終參考官方文檔。文檔

TA貢獻(xiàn)1796條經(jīng)驗 獲得超4個贊
如果您想驗證是否設(shè)置了一個而其他的為空:
注解
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Retention(RUNTIME)
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Constraint(validatedBy = OneNotNullValidator.class)
public @interface OneNotNull {
String message() default "Exactly one of the fields must be set and the other must be null";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
/**
* Fields to validate against null.
*/
String[] fields() default {};
}
驗證器
import java.util.Arrays;
import java.util.Objects;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.stereotype.Component;
@Component
public class OneNotNullValidator implements ConstraintValidator<OneNotNull, Object> {
private String[] fields;
@Override
public void initialize(final OneNotNull combinedNotNull) {
fields = combinedNotNull.fields();
}
@Override
public boolean isValid(final Object obj, final ConstraintValidatorContext context) {
final BeanWrapperImpl beanWrapper = new BeanWrapperImpl(obj);
return Arrays.stream(fields)
.map(beanWrapper::getPropertyValue)
.filter(Objects::isNull)
.count()
== 1;
}
}
用法
@OneNotNull(
fields = {"username","email"},
message="Either username or email must be set"
)
public class User {
private String username;
private String email;
// ...
}
添加回答
舉報