java Spring 验证:在可选字段上要求精确的长度
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28422894/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring Validation: Requiring an exact length on an optional field
提问by Marvo
In Spring MVC, I'm attempting to use annotations to perform validation of form input. I have some fields that are optional, but when input is provided, it must meet certain criteria. For example, I have one field that can be left blank, but when it is filled in, the answer must be exactly five characters long.
在 Spring MVC 中,我试图使用注释来执行表单输入的验证。我有一些可选的字段,但是当提供输入时,它必须满足某些条件。例如,我有一个可以留空的字段,但在填写时,答案必须正好是五个字符长。
I've tried things like
我试过这样的事情
@Size(min=5, max=5)
private String value;
but that gives the user an error if the user doesn't fill in the field.
但如果用户不填写该字段,则会给用户一个错误。
How can I provide some "rules" for an optional field?
如何为可选字段提供一些“规则”?
回答by mavarazy
- First option would be to set valueto null.
- 第一个选项是将值设置为 null。
If you take a look at SizeValidatorForCharSequence, used by hibernate:
如果您查看 Hibernate 使用的 SizeValidatorForCharSequence:
/**
* Check that the length of a character sequence is between min and max.
*
* @author Emmanuel Bernard
* @author Gavin King
* @author Hardy Ferentschik
*/
public class SizeValidatorForCharSequence implements ConstraintValidator<Size, CharSequence> {
private static final Log log = LoggerFactory.make();
private int min;
private int max;
public void initialize(Size parameters) {
min = parameters.min();
max = parameters.max();
validateParameters();
}
/**
* Checks the length of the specified character sequence (e.g. string).
*
* @param charSequence The character sequence to validate.
* @param constraintValidatorContext context in which the constraint is evaluated.
*
* @return Returns <code>true</code> if the string is <code>null</code> or the length of <code>charSequence</code> between the specified
* <code>min</code> and <code>max</code> values (inclusive), <code>false</code> otherwise.
*/
public boolean isValid(CharSequence charSequence, ConstraintValidatorContext constraintValidatorContext) {
if ( charSequence == null ) {
return true;
}
int length = charSequence.length();
return length >= min && length <= max;
}
private void validateParameters() {
if ( min < 0 ) {
throw log.getMinCannotBeNegativeException();
}
if ( max < 0 ) {
throw log.getMaxCannotBeNegativeException();
}
if ( max < min ) {
throw log.getLengthCannotBeNegativeException();
}
}
}
Size is invalid only if it's length does not match min, max constraints, and it's fine, if value is null.
仅当其长度与最小、最大约束不匹配时,大小才无效,如果值为空也没关系。
Another option would be to create your own annotation and validator:
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER }) @Retention(RUNTIME) @Documented @Constraint(validatedBy = { StringEmptyOrSizeValidator.class }) public @interface StringEmptyOrSize { String message() default "{javax.validation.constraints.Size.message}"; Class<?>[] groups() default { }; Class<? extends Payload>[] payload() default { }; /** * @return size the element must be higher or equal to */ int min() default 0; /** * @return size the element must be lower or equal to */ int max() default Integer.MAX_VALUE; /** * Defines several {@link Size} annotations on the same element. * * @see Size */ @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER }) @Retention(RUNTIME) @Documented @interface List { Size[] value(); } }
另一种选择是创建自己的注释和验证器:
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER }) @Retention(RUNTIME) @Documented @Constraint(validatedBy = { StringEmptyOrSizeValidator.class }) public @interface StringEmptyOrSize { String message() default "{javax.validation.constraints.Size.message}"; Class<?>[] groups() default { }; Class<? extends Payload>[] payload() default { }; /** * @return size the element must be higher or equal to */ int min() default 0; /** * @return size the element must be lower or equal to */ int max() default Integer.MAX_VALUE; /** * Defines several {@link Size} annotations on the same element. * * @see Size */ @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER }) @Retention(RUNTIME) @Documented @interface List { Size[] value(); } }
with validator
带验证器
public class StringEmptyOrSizeValidator implements ConstraintValidator<Size, CharSequence> {
....
public boolean isValid(CharSequence charSequence, ConstraintValidatorContext constraintValidatorContext) {
if ( charSequence == null || charSequence.isEmpty()) {
return true;
}
int length = charSequence.length();
return length >= min && length <= max;
}
....
}
回答by jvleminc
You could use the @Pattern(regexp="")annotation to allow customized patterns. Afterwards the error can shown with a Pattern.<bean>.value=...in your i12n property files.
您可以使用@Pattern(regexp="")注释来允许自定义模式。之后,错误可以在 i12n 属性文件中显示为Pattern.<bean>.value=...。
Example:
例子:
In bean "Person":
在 bean“人”中:
Pattern(regexp="^[A-Z?a-z?áéíóúáéíóú' -]{3,20}$")
private String names;
In messages.properties:
在messages.properties中:
Pattern.person.names=Please insert a valid name
回答by BaDr Amer
a more simple solution is to add a method into your class and add @AssertTrue annotation to it like this:
一个更简单的解决方案是在你的类中添加一个方法并像这样添加@AssertTrue 注释:
@AssertTrue
public boolean isValidValue() {
if(this.value == null || this.value.isEmpty()) {
return true;
}
else {
return this.value.length() == 5 ? false: true;
}
}
with this you don't need this: @Size(min=5, max=5)
有了这个,你就不需要这个了: @Size(min=5, max=5)