Dieser Artikel ist der Artikel zum 9. Tag von MicroAd Adventskalender 2017 . Da dies mein erster Versuch bei Qiita war, beschloss ich, eine Aufzeichnung als mein eigenes Memo zu führen. Bitte teilen Sie uns mit, wenn Sie Vorschläge wie falsche Informationen oder Auslassungen haben.
Lassen Sie uns ein Tool erstellen, das einfach ist, aber wiederverwendet werden kann. Originalanmerkungen sind ein kleiner Schritt in diese Richtung. Und ich kenne den Inhalt ein wenig.
~~ Das stimmt ~~
Ich möchte etwas ausprobieren, das mich anspricht. Aus irgendeinem Grund @ Dieses Symbol schien immer attraktiv. Wenn in Zukunft dieselbe Überprüfungslogik benötigt wird, müssen Sie lediglich eine Anmerkung hinzufügen, und es ist leicht zu erkennen, welche Art von Überprüfung durchgeführt wird.
Derzeit werden Anmerkungen in Java als Schnittstellen positioniert. Laut verknüpftem Zitat
The motivation for the introduction of annotations into the Java programming language was the need for semantic information for a given piece of code
Es wird als aus der Notwendigkeit heraus beschrieben, sich mit der "Bedeutung" eines bestimmten Codes in der Java-Programmierung zu befassen.
Im Folgenden sind typische Annotationsüberschreibungen aufgeführt, die als Standard-APIs bereitgestellt werden.
Override.java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
Die der Anmerkung beigefügte Anmerkung lautet Dies ist eine Meta-Annotation, die vom Paket java.lang.annotation bereitgestellt wird.
@Target
Es ist das zu kommentierende Ziel. Sie können mehrere angeben, indem Sie sie in `` {}
`einfügen.
Als Zieltyp
Es gibt mehrere, aber im Fall von @Override wird METHOD als Ziel ausgewählt. Tatsächlich kann @Override nicht an andere Elemente als Methoden angehängt werden.
@Retention Beschreibt den Bereich, der von der Anmerkung betroffen ist. Retention gibt eine RetentionPolicy zurück, und es gibt nur drei Arten von RetentionPolicy.
SOURCE: Diese Anmerkung wird beim Kompilieren verworfen
CLASS (Standard): Wird in der Klassendatei aufgezeichnet, aber zur Laufzeit nicht beibehalten
RUNTIME: Wird in der Klassendatei aufgezeichnet und kann zur Laufzeit referenziert werden == Die Informationen dieser Anmerkung werden in die Laufzeit-JVM geladen.
Im Fall von @Override ist RetentionPolicy SOURCE Am Ende der Kompilierung hat dies keine Bedeutung == Die Bytecode-Konvertierung wird nicht durchgeführt.
In einigen Fällen werden sowohl Ziel als auch Aufbewahrung aus Gründen der Lesbarkeit einfach als "Import statisch" geschrieben.
Was ich diesmal wollte, war eine Anmerkung, um halbe Breite und volle Breite getrennt zu zählen </ b> und die maximale Länge </ b> zu begrenzen. Für die Vorlage habe ich allgemein auf das Paket javax.validation.constraints verwiesen (@Size und @NotNull, richtig?).
Tatsächlich hat diese ursprüngliche Annotation, dh die Constraint-Annotation, eine feste Vorlage (message (), groups (), payload () muss festgelegt werden). Erstellen Sie sie daher entsprechend.
Ich werde es einen Namen geben.
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 Gibt an, dass zum Verwenden dieser Anmerkung das Schreiben mit Javadoc usw. erforderlich ist. Um ehrlich zu sein, habe ich es diesmal vielleicht nicht gebraucht.
@Constraint Geben Sie die Klasse an, die die spezifische Logik beschreibt, die Sie mit dieser Annotation einschränken (prüfen) möchten. Das Folgende ist die Validierungsimplementierungsklasse für diese 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 ist eine Klasse, die nur die Prüflogik beschreibt
//Der Rückgabewert von getLength ist int
return CustomSizeUtil.getLength(value) <= max;
}
}
initialize </ b> ist der Initialisierungsprozess zum Aufrufen von `` `isValid```.
isValid </ b> implementiert die eigentliche Validierungslogik. Der als Parameter übergebene `<T> -Wert
`ist das tatsächlich zu überprüfende Objekt.
Dieses Mal wird die Länge der eingegebenen Zeichenfolge überprüft, sodass eine Zeichenfolge vom Typ Zeichenfolge dieser entspricht.
Wenn `` `value``` die Prüfung aufgrund einer ungültigen Werteingabe nicht bestehen kann, wird false zurückgegeben.
message() Diese Meldung ist als Warnung (?) Auszugeben, wenn eine falsche Eingabe erfolgt. Enthält den Wortlaut, der in den Nachrichteneigenschaften definiert werden soll (z. B. ValidationMessages.properties von Hibernate). Außerdem wird der Schlüssel mit einem vollständig qualifizierten Klassennamen geschrieben.
Zum Beispiel denke ich, dass es so aussehen wird.
ValidationMessages_jp.properties
validation.CustomSize.message = {0}Bitte nicht überschreiten
groups() Diese Einstellung kann für eine bestimmte Validierungsgruppe angepasst werden. Muss mit einem leeren Klassentyp <?> Initialisiert werden.
Die Gruppierung dient zum Bestellen von Einschränkungen.
@GroupSequence({CheckA.class, CheckB.class}) //Nach Überprüfung von A B.
public interface GroupedChecks {
}
payload() Es handelt sich lediglich um eine Deklaration, um dem zu überprüfenden Objekt einige Metainformationen zu geben. Tatsächlich denke ich, dass der Inhalt der `` `javax.validation.Payload``` -Schnittstelle leer ist und für Markierungen oder Kategorisierung dient.
Zum Beispiel
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
}
Es ist nicht korrekt, aber Sie können dem Feld "Memo" eine Bedeutung geben, damit es als Kategorisierung wie "Text" identifiziert werden kann.
Lassen Sie es leer, sofern nicht anders angegeben.
max() Dieses Mal habe ich den Namen max festgelegt, da es sich um eine Validierung handelt, die die "maximale Länge" einschränkt.
@CustomSizeValidator(max = 20) //Name hier eingeben
private String memo;
List { A[] value() } Definieren Sie die überprüfbaren Ziele in Abhängigkeit von der Implementierung von ConstraintValidator.
@interface List {
CustomSizeValidator value();
AnotherValidator aaa();
}
Sofern Sie keinen bestimmten Grund haben, kann ein Element ausreichen.
Es ist dasselbe wie bei anderen Eingabeprüfungen, fügt jedoch @Valid zum oberen Modell hinzu, das als Parameter des Controllers übergeben wurde, und definiert BindingResult, indem es direkt daneben angeordnet wird.
SampleController.java
@RequestMapping(value = "/sample", method = RequestMethod.POST)
public String samplePost(@ModelAttribute @Valid BigModel model, BindingResult result) {
// omit
}
Fügen Sie bei verschachtelten Modellen dem oberen Modell ebenfalls @Valid hinzu.
BigModel.java
public class BigModel {
@Valid
private SmallModel smallModel;
// omit
}
Diese benutzerdefinierte Anmerkung lautet @Target ({ElementType.FIELD}) und zielt daher auf Felder ab. Fügen Sie es dem Feld hinzu, das tatsächlich überprüft werden soll.
SmallModel.java
public class SmallModel {
@CustomSize(max = 20)
private String input;
// omit
}
Testen Sie, um die App auszuführen und versuchen Sie es direkt (Fehler wird in `` `BindingResult``` gespeichert)
Test mit Testcode (geben Sie einige Werte an und berechnen Sie wirklich genau)
Da es sich um eine Zeichenanzahl mit einer festen Grenze handelt, habe ich sie mit einer Grenzwertanalyse getestet.
Ich teste die Implementierungsklasse für Annotationsbeschränkungen `isValid ()`
.
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
Es war einfach, so etwas zu tun. Ich wollte es in ungefähr beenden Immerhin war es sehr interessant, die Inhalte zu kennen, und es war eine sehr gute Gelegenheit, um zu studieren.
Hibernate Community Documentation
das ist alles