2011-08-04 4 views
4

J'utilise la validation de beans JSR-303 et Spring 3 et je dois fournir différentes valeurs pour l'annotation en fonction du cas d'utilisation. Par exemple, la valeur du paramètre min dans @Size(min=?) doit être 1 pour une validation et 5 pour un autre cas, et je souhaite lire ces valeurs à partir d'un fichier de propriétés. Par exemple, la valeur minValeurs de validation JSR-303 paramétrables

Je sais que le paramètre de message peut être lu à partir du fichier ValidationMessages.properties s'il est fourni en tant que clé mais qu'en est-il de l'autre paramètre?

Répondre

3

Les valeurs des paramètres d'annotation ne peuvent être que des expressions de compilation. Cela signifie que pour le @Size(min=X, max=Z) X et Z doivent être résolvables au moment de la compilation.

Depuis min et max sont déclarés comme int sur @Size, vous êtes bloqué.

Si vous avez besoin de valeurs différentes pour min, Je vois personnellement deux façons de le faire.

D'abord, vous pouvez utiliser un regroupement sur les validateurs. Utilisez un groupe pour min=1 et un groupe pour min=5. Par exemple, laisse envisager une Test classe:

public class Test { 
    @NotNull 
    @Size.List({ 
    @Size(min = 1, groups = GroupOne.class), 
    @Size(min = 5, groups = GroupTwo.class) 
    }) 
    private String prop; 

    public String getProp() { 
    return prop; 
    } 
    public void setProp(String prop) { 
    this.prop = prop; 
    } 
} 

Vous devez déclarer les groupes:

public interface GroupOne {} 
public interface GroupTwo {} 

Ensuite, créez un objet de test ainsi que le validateur pour aller avec elle:

Test test = new Test(); 
test.setProp("XY"); 

ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); 
Validator validator = factory.getValidator(); 

Ensuite, validez en utilisant les groupes:

Set<ConstraintViolation<Test>> resultOne = validator.validate(test, GroupOne.class); 
Set<ConstraintViolation<Test>> resultTwo = validator.validate(test, GroupTwo.class); 

Le premier cas est valide depuis min=1 et "XY".length() == 2 mais le second échouera car min=5.

Cette méthode consiste à faire la validation manuelle et je ne pense pas que vous pouvez simplement compter sur @Valid sur une @RequestMapping méthode annotée de faire la validation (depuis @Valid est juste un déclencheur pour la validation avec aucun moyen de mentionner le groupe requis pour validation). Luckly Spring est très flexible et il n'y aura pas beaucoup de frais généraux pour appeler le validateur vous-même.

La deuxième option que je vois consiste à créer votre propre annotation de validation avec un validateur personnalisé pour correspondre. Here you can find a simple example to get you started. Avec cette solution, vous pouvez déclarer min et max comme des clés de chaîne que votre validateur va résoudre dans les bundles avant la validation. Cette solution est cependant plus lourde que la première.

+1

Je pense que les annotations personnalisées + le validateur sont la solution. Il pourrait implémenter une annotation '@ DynMin' qui s'appellerait' @DynMin (min = "{my.property.somewhere}") et qui utiliserait une classe de validateur personnalisée, qui lirait la propriété et la validerait (en utilisant la référence validateur d'implémentation, par exemple). –

3

Comme indiqué par dpb, vous pouvez utiliser validation groups pour spécifier la même contrainte avec différentes valeurs d'attribut.

Si vous travaillez avec Hibernate Validator comme implémentation BV, vous pouvez utiliser le programmatic API au lieu des annotations pour définir vos contraintes.De cette façon, vous pouvez récupérer les valeurs de contrainte concrètes au moment de l'exécution comme ceci:

int minValue1 = ...; //read from properties file etc. 
int minValue2 = ...; 

//programmatically define the constraints for the Test type 
ConstraintMapping mapping = new ConstraintMapping(); 
mapping.type(Test.class) 
    .property("prop", FIELD) 
     .constraint(new NotNullDef()) 
     .constraint(new SizeDef().min(minValue1).groups(GroupOne.class)) 
     .constraint(new SizeDef().min(minValue2).groups(GroupTwo.class)); 

//retrieve a validator using the programmatic constraint mapping 
HibernateValidatorConfiguration config = 
    Validation.byProvider(HibernateValidator.class).configure(); 
config.addMapping(mapping); 
ValidatorFactory factory = config.buildValidatorFactory(); 
Validator validator = factory.getValidator(); 
Questions connexes