Java Play 2 - How would you define a maxlength con

2019-04-15 10:19发布

Using Play 2.3 (Java), I'd like to use a parameter from application.conf as a value for a constraint. Something like:

public class Some {
    @Constraints.MaxLength(Play.application().configuration().getInt("some.text.maxlength", 1000))
    public String text;
}

But of course I can't do this because the annotation parameter must be a constant. What would be the approach, in Java, to bypass this? Should I use a custom validator? Or is there another option?

Any help appreciated.

1条回答
倾城 Initia
2楼-- · 2019-04-15 10:39

As you discovered you can't use it via annotations, but fortunately you can write own constraints and read the application.conf within it, fast sample based on MinLength constraint:

file: app/utils/MyConstraints.java

package utils;

import play.Play;
import play.libs.F;

import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static play.libs.F.Tuple;

public class MyConstraints {

    public static abstract class Validator<T> {

        public abstract boolean isValid(T object);

        public boolean isValid(T object, ConstraintValidatorContext constraintContext) {
            return isValid(object);
        }

        public abstract Tuple<String, Object[]> getErrorMessageKey();

    }

    @Target({FIELD})
    @Retention(RUNTIME)
    @Constraint(validatedBy = SomeTextMinLengthValidator.class)
    @play.data.Form.Display(name="constraint.minLength")
    public static @interface SomeTextMinLength {
        String message() default SomeTextMinLengthValidator.message;
        Class<?>[] groups() default {};
        Class<? extends Payload>[] payload() default {};
    }

    public static class SomeTextMinLengthValidator extends Validator<String> implements ConstraintValidator<SomeTextMinLength, String> {

        final static public String message = "error.minLength";
        private long min;

        public SomeTextMinLengthValidator() {}

        public SomeTextMinLengthValidator(long value) {
            this.min = value;
        }

        public void initialize(SomeTextMinLength constraintAnnotation) {
            this.min = Play.application().configuration().getInt("some.text.maxlength", 1000);
        }

        public boolean isValid(String object) {
            if (object == null || object.length() == 0) {
                return true;
            }

            return object.length() >= min;
        }

        public F.Tuple<String, Object[]> getErrorMessageKey() {
            return Tuple(message, new Object[] { min });
        }
    }
}

usage:

@utils.MyConstraints.SomeTextMinLength
public String text;

As you can see to add more constraints like that you only need to add the pairs of MyFooConstraint and MyFooConstraintValidator into MyConstraints class, so you can also make it more generic:

@Target({FIELD})
@Retention(RUNTIME)
@Constraint(validatedBy = MinLengthByCfgValidator.class)
@play.data.Form.Display(name="constraint.minLength", attributes={"configKey","defaultValue"})
public static @interface MinLengthByCfg {
    String message() default MinLengthByCfgValidator.message;
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
    String configKey();
    long defaultValue();
}

public static class MinLengthByCfgValidator extends Validator<String> implements ConstraintValidator<MinLengthByCfg, String> {

    final static public String message = "error.minLength";
    private long min;

    public MinLengthByCfgValidator() {}

    public void initialize(MinLengthByCfg constraintAnnotation) {

        this.min = Play.application().configuration().getLong(
                constraintAnnotation.configKey(),
                constraintAnnotation.defaultValue()
                );
    }

    public boolean isValid(String object) {
        if (object == null || object.length() == 0) {
            return true;
        }

        return object.length() >= min;
    }

    public F.Tuple<String, Object[]> getErrorMessageKey() {
        return Tuple(message, new Object[] {min});
    }

}

and then use it like:

@utils.MyConstraints.MinLengthByCfg(configKey = "some.text.maxlength", defaultValue = 3)
public String text;
查看更多
登录 后发表回答