Cet article est le 9ème jour du Calendrier de l'avent MicroAd 2017 . Comme c'était ma première tentative à Qiita, j'ai décidé de garder un enregistrement comme mon propre mémo. Veuillez nous faire savoir si vous avez des suggestions telles que des informations incorrectes ou des omissions.
Faisons un outil facile mais réutilisable. Les annotations originales sont un petit pas dans cet effort. Et je connais un peu le contenu.
~~ C'est vrai ~~
Je veux essayer quelque chose qui me plaît. Pour une raison quelconque @ Ce symbole a toujours semblé attrayant. De plus, lorsque la même logique de vérification est nécessaire à l'avenir, il suffit d'ajouter une annotation et il est facile de voir quel type de vérification sera effectué.
Pour le moment, les annotations en java sont positionnées comme des interfaces. Selon citation liée
The motivation for the introduction of annotations into the Java programming language was the need for semantic information for a given piece of code
Il est décrit comme résultant de la nécessité de traiter le "sens" d'un code donné dans la programmation java.
Voici les remplacements d'annotations typiques fournis en tant qu'API standard.
Override.java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
L'annotation attachée à l'annotation est Il s'agit d'une méta-annotation fournie par le package java.lang.annotation.
@Target C'est la cible à annoter. Vous pouvez en spécifier plusieurs en les mettant entre `` {} ''. Comme type de cible
Il y en a plusieurs, mais dans le cas de @Override, METHOD est ciblé. En fait, @Override ne peut pas être attaché à des éléments autres que des méthodes.
@Retention Décrit la plage affectée par l'annotation. Retention renvoie un RetentionPolicy et il n'existe que trois types de RetentionPolicy.
SOURCE: Cette annotation est supprimée au moment de la compilation
CLASS (par défaut): Enregistré dans le fichier de classe mais pas conservé à l'exécution
RUNTIME: enregistré dans le fichier de classe et peut être référencé à l'exécution == Les informations de cette annotation sont chargées dans la JVM d'exécution.
Dans le cas de @Override, RetentionPolicy est SOURCE, donc A la fin de la compilation, cela n'a aucune signification == Il ne sera pas converti en byte code.
Dans certains cas, Target et Retention sont simplement écrits comme import static
pour plus de lisibilité.
Ce que je voulais cette fois, c'était une annotation pour compter séparément la demi-largeur et la pleine largeur </ b> et limiter la longueur maximale </ b>. Pour le modèle, je me suis généralement référé au package javax.validation.constraints (@Size et @NotNull, non?).
En fait, cette annotation d'origine, c'est-à-dire l'annotation de contrainte, a un modèle fixe (message (), groups (), payload () doivent être définis), alors créez-le en conséquence.
Je vais lui donner un nom.
CustomSize.java
@Target({FIELD})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {CustomSizeValidator.class})
public @interface CustomSize {
String message() default "{validation.CustomSize.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
int max();
@Target({FIELD})
@Retention(RUNTIME)
@Documented
@interface List {
CustomSize[] value();
}
}
@Documented Indique que l'écriture avec javadoc etc. est nécessaire pour utiliser cette annotation. Pour être honnête, je n'en ai peut-être pas eu besoin cette fois.
@Constraint Spécifiez la classe qui décrit la logique spécifique que vous souhaitez contraindre (vérifier) avec cette annotation. Voici la classe d'implémentation de validation pour cette annotation.
CustomSizeValidator.java
public class CustomSizeValidator implements ConstraintValidator<CustomSize, String> {
private int max;
@Override
public void initialize(CustomSize customSize) {
max = customSize.max();
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
//CustomSizeUtil est une classe qui décrit uniquement la logique de contrôle
//La valeur de retour de getLength est int
return CustomSizeUtil.getLength(value) <= max;
}
}
initialize </ b> est le processus d'initialisation pour appeler isValid
.
isValid </ b> implémente la logique de validation réelle. La
Si `` valeur '' ne peut pas être vérifiée en raison d'une valeur incorrecte saisie, false est renvoyé.
message() Ce message est un avertissement (?) Lorsqu'une entrée incorrecte est effectuée. Contient le libellé à définir dans les propriétés du message (telles que ValidationMessages.properties d'Hibernate). En outre, la clé est écrite avec un nom de classe complet.
Par exemple, je pense que cela ressemblera à ceci.
ValidationMessages_jp.properties
validation.CustomSize.message = {0}Veuillez ne pas dépasser
groups() C'est un paramètre qui peut être personnalisé pour un groupe de validation spécifique. Doit être initialisé avec un type de classe <?> Vide.
Le regroupement sert à ordonner les contraintes.
@GroupSequence({CheckA.class, CheckB.class}) //Après avoir vérifié A B
public interface GroupedChecks {
}
payload()
C'est une déclaration uniquement pour donner des méta-informations à l'objet à vérifier.
En fait, je pense que le contenu de l'interface
javax.validation.Payload``` est vide et est destiné aux marqueurs ou à la catégorisation.
Par exemple
CustomSize.java
@Target({FIELD})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {CustomSizeValidator.class})
public @interface CustomSize {
String message() default "{validation.CustomSize.message}";
Class<?>[] groups() default {};
class Text implements Payload{} // Add Payload
// omit
}
SampleModel.java
public class SampleModel {
@CustomSizeValidator(max = 20, payload = {CustomSizeValidator.Text.class})
private String memo;
// omit
}
Ce n'est pas correct, mais vous pouvez donner un sens au champ mémo '' afin qu'il puisse être identifié comme une catégorisation telle que
Texte ''.
Laissez-le vide sauf indication contraire.
max() Cette fois, j'ai mis le nom max car c'est une validation qui limite la "longueur maximale".
@CustomSizeValidator(max = 20) //Nom à saisir ici
private String memo;
List { A[] value() } Définissez la ou les cibles vérifiables en fonction de l'implémentation de ConstraintValidator.
@interface List {
CustomSizeValidator value();
AnotherValidator aaa();
}
Sauf si vous avez une raison spécifique, un élément peut suffire.
C'est la même chose que les autres vérifications d'entrée, mais ajoutez @Valid au modèle supérieur passé comme paramètre du contrôleur et définissez BindingResult en le disposant immédiatement à côté.
SampleController.java
@RequestMapping(value = "/sample", method = RequestMethod.POST)
public String samplePost(@ModelAttribute @Valid BigModel model, BindingResult result) {
// omit
}
Pour les modèles imbriqués, ajoutez également @Valid au modèle supérieur.
BigModel.java
public class BigModel {
@Valid
private SmallModel smallModel;
// omit
}
Cette annotation personnalisée est @Target ({ElementType.FIELD}), elle cible donc le champ. Attachez-le au champ à vérifier.
SmallModel.java
public class SmallModel {
@CustomSize(max = 20)
private String input;
// omit
}
Testez pour exécuter l'application et essayez-la directement (l'erreur est stockée dans
BindingResult```)
Test avec code de test (donnez quelques valeurs et calculez vraiment exactement)
Puisqu'il s'agit d'un nombre de caractères avec une limite fixe, je l'ai testé avec une analyse des valeurs limites. Je teste le «isValid ()» «de la classe d'implémentation de la contrainte d'annotation.
CustomTest.groovy
// omit
when:
def result = validator.isValid("", null)
then:
assert result == excepted
where:
testCase | maxLen | doubleLen || excepted
"Boundary value, small" | 5 | 4.5 || true
"Boundary value, same" | 5 | 5 || true
"Boundary value, big" | 5 | 5.5 || false
C'était facile de faire quelque chose comme ça. J'avais l'intention de le terminer dans environ Après tout, c'était très intéressant d'en connaître le contenu et c'était une très bonne occasion d'étudier.
Hibernate Community Documentation
c'est tout
Recommended Posts