[JAVA] Comment transmettre une valeur autre que l'attribut d'annotation au message Hibernate Validator (Bean Validation) (méthode d'incorporation)

Vous pouvez incorporer la valeur d'attribut spécifiée dans l'annotation de contrainte dans le message d'erreur Bean Validation comme suit. (Notez que le contenu traité dans cette entrée est basé sur l'utilisation d'Hibernate Validator)

Exemple de spécification d'annotation de contrainte


@Size(min = 4, max = 16)
private String foo;

Exemple d'exécution de validation


// ...
Bean bean = new Bean();
bean.foo = "123";
Set<ConstraintViolation<Bean>> violations = vb.validate(bean);
// ...

Le message d'erreur généré dans le cas ci-dessus serait "la taille doit être comprise entre 4 et 16".

L'arrière-plan que je voulais intégrer autre que la valeur de l'attribut d'annotation est ...

Dans le cas sur lequel je travaille maintenant, j'ai été obligé d'obtenir la valeur de référence à laquelle faire référence lors de la vérification de l'entrée du paramètre externe (en fait le fichier de propriétés). Il y avait une option pour vérifier avec la logique sans utiliser la validation de Bean, mais je voulais utiliser le mécanisme de validation de Bean autant que possible pour la vérification des entrées, j'ai donc étudié comment le réaliser avec la validation de Bean.

Plus précisément, quel type d'annotation de contrainte avez-vous créé?

Bien qu'elle n'ait pas été réellement créée, j'ai décidé de créer une annotation qui vérifie «la date est après le nombre de jours spécifié» et de créer une annotation de contrainte qui récupère la partie «nombre de jours spécifié» du fichier de propriété. ..

Exemple de création d'annotation de contrainte


@DaysLater(days = "foo.daysLater", defaultValue = 5)
private LocalDate fooDate;

Exemple de configuration de fichier de propriété


foo.daysLater=10

src/main/resources/ValidationMessages.Exemple de définition des propriétés


com.example.validation.DaysLater.message = must be {days} days later

J'ai pu le vérifier, mais le message est décevant ...

Je voudrais dire "doit être 10 jours plus tard" comme message d'erreur lorsque la contrainte est violée, mais malheureusement le comportement par défaut est "doit être foo.daysLater jours plus tard". Eh bien, c'est un résultat naturel ...

Est-il possible de se conformer aux spécifications de Bean Validation?

Je ne l'ai pas fait correctement, mais quand j'ai regardé les spécifications, il ne semblait y avoir aucun moyen de le traiter dans les spécifications de validation Bean. Cependant, étant donné que la formule EL peut être utilisée lors de l'assemblage du message, il peut être possible de la traiter en maîtrisant la formule EL.

Il peut être pris en charge en utilisant la fonction d'extension de Hibernate Validator!

Lors de l'utilisation de Extension fournie par Hibernate Validation, le message Vous pouvez modifier les valeurs qui peuvent être référencées à partir de la définition.


private int value; //Stocker la valeur de propriété à partir de la valeur d'attribut (clé de propriété) de l'annotation

// ...

public boolean isValid(LocalDate targetValue, ConstraintValidatorContext context) {

  boolean result = //Vérifier le contenu omis...
  
    //Si la vérification est NG, l'opération par défaut est invalidée et des informations de violation de contrainte arbitraires sont générées.
  if (!result) {
    //Conversion vers l'interface fournie par Hibernate Validator pour utiliser l'extension de Hibernate Validator
    HibernateConstraintValidatorContext hibernateContext =
        context.unwrap(HibernateConstraintValidatorContext.class);

    //Désactiver la génération des informations de violation de contrainte par défaut
    hibernateContext.disableDefaultConstraintViolation();

    //Générer des informations de violation de contrainte arbitraires
    hibernateContext
        //Dans la définition du message{value}Pour pouvoir se référer à la valeur avec
        .addMessageParameter("days", this.days)
        //Autoriser la valeur à être référencée par la valeur du nom de variable dans l'expression EL dans la définition de message
        .addExpressionVariable("days", this.days)
        //Le modèle de message utilise le modèle spécifié dans l'annotation (identique au comportement par défaut)
        .buildConstraintViolationWithTemplate(hibernateContext.getDefaultConstraintMessageTemplate())
        //Ajouter des informations de violation de contrainte
        .addConstraintViolation();
  }
  return result;
}

Avec l'implémentation ci-dessus, il est possible d'incorporer la valeur correspondant à la clé de propriété au lieu de la clé de propriété dans le message. En utilisant ce mécanisme, il est également possible d'incorporer une «date à laquelle le chèque est OK» dans le message.

public boolean isValid(LocalDate targetValue, ConstraintValidatorContext context) {

  LocalDate validMinDate = LocalDate.now().plusDays(value);
  boolean result = //Vérifier le contenu omis...
  
  if (!result) {
    HibernateConstraintValidatorContext hibernateContext =
        context.unwrap(HibernateConstraintValidatorContext.class);
    hibernateContext.disableDefaultConstraintViolation();
    hibernateContext
        .addMessageParameter("days", this.days)
        .addExpressionVariable("days", this.days)
        //Ajout de la date à laquelle le chèque est OK
        .addMessageParameter("validMinDate", validMinDate)
        .addExpressionVariable("validMinDate", validMinDate)
        .buildConstraintViolationWithTemplate(hibernateContext.getDefaultConstraintMessageTemplate())
        .addConstraintViolation();
  }
  return result;
}

src/main/resources/ValidationMessages.properties


com.example.validation.DaysLater.message = must be {validMinDate} or later

Le message d'erreur lorsque la contrainte n'est pas respectée est "doit être le 26/09/2018 ou une version ultérieure", ce qui peut être un message plus intuitif.

Résumé

Si c'est un prérequis pour fonctionner sur Hibernate Validator, il sera plus facile de composer des messages avec une grande convivialité en utilisant l'extension introduite cette fois. Le projet sur lequel je travaille actuellement peut être exécuté sur Hivernate Validator, donc je pense utiliser efficacement ce mécanisme.

Recommended Posts

Comment transmettre une valeur autre que l'attribut d'annotation au message Hibernate Validator (Bean Validation) (méthode d'incorporation)
Comment créer une méthode
[Swift5] Comment communiquer de ViewController à Model et transmettre une valeur
Comment passer la valeur à un autre écran