Eri*_*ric 72 java validation bean-validation
我想用JSR-303做一点自定义验证javax.validation.
我有一个领域.如果在此字段中输入了某个值,我想要求其他几个字段不是null.
我想弄清楚这一点.不确定我会称之为什么来帮助找到解释.
任何帮助,将不胜感激.我对此很新.
目前我正在考虑自定义约束.但我不确定如何从注释中测试依赖字段的值.基本上我不确定如何从注释访问面板对象.
public class StatusValidator implements ConstraintValidator<NotNull, String> {
@Override
public void initialize(NotNull constraintAnnotation) {}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if ("Canceled".equals(panel.status.getValue())) {
if (value != null) {
return true;
}
} else {
return false;
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是panel.status.getValue();给我带来麻烦..不知道如何实现这一目标.
h22*_*h22 92
定义必须验证为true的方法并将@AssertTrue注释放在其顶部:
@AssertTrue
private boolean isOk() {
return someField != something || otherField != null;
}
Run Code Online (Sandbox Code Playgroud)
该方法必须以'is'开头.
Sla*_*hin 89
在这种情况下,我建议编写自定义验证器,它将在类级别进行验证(以允许我们访问对象的字段),只有当另一个字段具有特定值时才需要一个字段.请注意,您应该编写通用验证器,它获取2个字段名称并仅使用这2个字段.要要求多个字段,您应该为每个字段添加此验证器.
使用以下代码作为一个想法(我没有测试它).
验证器接口
/**
* Validates that field {@code dependFieldName} is not null if
* field {@code fieldName} has value {@code fieldValue}.
**/
@Target({TYPE, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = NotNullIfAnotherFieldHasValueValidator.class)
@Documented
public @interface NotNullIfAnotherFieldHasValue {
String fieldName();
String fieldValue();
String dependFieldName();
String message() default "{NotNullIfAnotherFieldHasValue.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
@Target({TYPE, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Documented
@interface List {
NotNullIfAnotherFieldHasValue[] value();
}
}
Run Code Online (Sandbox Code Playgroud)验证器实现
/**
* Implementation of {@link NotNullIfAnotherFieldHasValue} validator.
**/
public class NotNullIfAnotherFieldHasValueValidator
implements ConstraintValidator<NotNullIfAnotherFieldHasValue, Object> {
private String fieldName;
private String expectedFieldValue;
private String dependFieldName;
@Override
public void initialize(NotNullIfAnotherFieldHasValue annotation) {
fieldName = annotation.fieldName();
expectedFieldValue = annotation.fieldValue();
dependFieldName = annotation.dependFieldName();
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext ctx) {
if (value == null) {
return true;
}
try {
String fieldValue = BeanUtils.getProperty(value, fieldName);
String dependFieldValue = BeanUtils.getProperty(value, dependFieldName);
if (expectedFieldValue.equals(fieldValue) && dependFieldValue == null) {
ctx.disableDefaultConstraintViolation();
ctx.buildConstraintViolationWithTemplate(ctx.getDefaultConstraintMessageTemplate())
.addNode(dependFieldName)
.addConstraintViolation();
return false;
}
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ex) {
throw new RuntimeException(ex);
}
return true;
}
}
Run Code Online (Sandbox Code Playgroud)验证器用法示例
@NotNullIfAnotherFieldHasValue.List({
@NotNullIfAnotherFieldHasValue(
fieldName = "status",
fieldValue = "Canceled",
dependFieldName = "fieldOne"),
@NotNullIfAnotherFieldHasValue(
fieldName = "status",
fieldValue = "Canceled",
dependFieldName = "fieldTwo")
})
public class SampleBean {
private String status;
private String fieldOne;
private String fieldTwo;
// getters and setters omitted
}
Run Code Online (Sandbox Code Playgroud)请注意,验证器实现使用库中的BeanUtils类,commons-beanutils但您也可以使用BeanWrapperImplSpring Framework.
另请参阅这个很好的答案:使用Hibernate Validator进行交叉字段验证(JSR 303)
use*_*153 15
你应该使用自定义DefaultGroupSequenceProvider<T>:
// Marker interface
public interface ConditionalValidation {}
Run Code Online (Sandbox Code Playgroud)
public class MyCustomFormSequenceProvider
implements DefaultGroupSequenceProvider<MyCustomForm> {
@Override
public List<Class<?>> getValidationGroups(MyCustomForm myCustomForm) {
List<Class<?>> sequence = new ArrayList<>();
// Apply all validation rules from ConditionalValidation group
// only if someField has given value
if ("some value".equals(myCustomForm.getSomeField())) {
sequence.add(ConditionalValidation.class);
}
// Apply all validation rules from default group
sequence.add(MyCustomForm.class);
return sequence;
}
}
Run Code Online (Sandbox Code Playgroud)
@GroupSequenceProvider(MyCustomFormSequenceProvider.class)
public class MyCustomForm {
private String someField;
@NotEmpty(groups = ConditionalValidation.class)
private String fieldTwo;
@NotEmpty(groups = ConditionalValidation.class)
private String fieldThree;
@NotEmpty
private String fieldAlwaysValidated;
// getters, setters omitted
}
Run Code Online (Sandbox Code Playgroud)
另请参阅有关此主题的相关问题.
这是我的看法,试图使其尽可能简单。
界面:
@Target({TYPE, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = OneOfValidator.class)
@Documented
public @interface OneOf {
String message() default "{one.of.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
String[] value();
}
Run Code Online (Sandbox Code Playgroud)
验证实施:
public class OneOfValidator implements ConstraintValidator<OneOf, Object> {
private String[] fields;
@Override
public void initialize(OneOf annotation) {
this.fields = annotation.value();
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(value);
int matches = countNumberOfMatches(wrapper);
if (matches > 1) {
setValidationErrorMessage(context, "one.of.too.many.matches.message");
return false;
} else if (matches == 0) {
setValidationErrorMessage(context, "one.of.no.matches.message");
return false;
}
return true;
}
private int countNumberOfMatches(BeanWrapper wrapper) {
int matches = 0;
for (String field : fields) {
Object value = wrapper.getPropertyValue(field);
boolean isPresent = detectOptionalValue(value);
if (value != null && isPresent) {
matches++;
}
}
return matches;
}
private boolean detectOptionalValue(Object value) {
if (value instanceof Optional) {
return ((Optional) value).isPresent();
}
return true;
}
private void setValidationErrorMessage(ConstraintValidatorContext context, String template) {
context.disableDefaultConstraintViolation();
context
.buildConstraintViolationWithTemplate("{" + template + "}")
.addConstraintViolation();
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
@OneOf({"stateType", "modeType"})
public class OneOfValidatorTestClass {
private StateType stateType;
private ModeType modeType;
}
Run Code Online (Sandbox Code Playgroud)
讯息:
one.of.too.many.matches.message=Only one of the following fields can be specified: {value}
one.of.no.matches.message=Exactly one of the following fields must be specified: {value}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
80971 次 |
| 最近记录: |