Guten Tag, Habr!
Nach einiger Zeit beschloss ich, hier noch einmal zu schreiben und meine Erfahrungen zu teilen. In diesem Artikel geht es darum, wie Standardvalidatoren angepasst und unter Verwendung der Spring-Aspekte überall dort aufgerufen werden, wo wir sie benötigen. Nun, es hat mich ermutigt zu schreiben - das Fehlen solcher Informationen, insbesondere auf Russisch.
Das Problem
Das Wesentliche der Anwendung ist also ungefähr das Folgende: Es gibt eine Gateway-API, die die Anforderung akzeptiert und sie weiter modifiziert und an die entsprechende Bank weiterleitet. Die Anfrage für jede Bank war jedoch unterschiedlich - ebenso wie die Validierungsparameter. Daher war es nicht möglich, die ursprüngliche Anforderung zu validieren. Es gab zwei Möglichkeiten: Anmerkungen aus javax.validation zu verwenden oder eine eigene separate Validierungsschicht zu schreiben. Im ersten Fall gab es einen Haken - standardmäßig können Objekte nur in der Steuerung validiert werden. Im zweiten Fall gab es auch Minuspunkte - dies ist eine zusätzliche Ebene, eine große Menge an Code, und selbst wenn sich die Modelle ändern würden, müssten die Validatoren geändert werden.
Daher wurde beschlossen, einen Weg zu finden, um Standardvalidatoren bei Bedarf und nicht nur in der Steuerung abzurufen.
Wir ziehen Validatoren
Nach ein paar Stunden in Google wurden einige Lösungen gefunden, von denen die geeignetste darin bestand, javax.validation.Validator automatisch zu verdrahten und die validate-Methode darauf aufzurufen, an die Sie ein validiertes Objekt als Parameter übergeben müssen.
Es scheint, dass eine Lösung gefunden wurde, aber überall zu validieren, schien Validator keine gute Idee zu sein, ich wollte eine elegantere Lösung.
AOP hinzufügen
Ohne nachzudenken, beschloss ich,
meine Lieblingsaspekte an diese Lösung anzupassen.
Die Logik war ungefähr die folgende: Erstellen Sie eine Anmerkung und hängen Sie sie an eine Methode, die ein Objekt in ein anderes konvertiert. Im weiteren Verlauf fangen wir alle mit dieser Annotation gekennzeichneten Methoden ab und rufen die Validierungsmethode für den von ihnen zurückgegebenen Wert auf. Gewinn
Also Anmerkung:
Eine Methode zum Konvertieren von Abfragen ist:
@Validate public SomeBankRequest requestToBankRequest(Request<T> request) { SomeBankRequest bankRequest = ...; ...
Nun, eigentlich der Aspekt selbst:
@Aspect @Component public class ValidationAspect { private final Validator validator;
Kurz zum Arbeitsaspekt:
Wir fangen das Objekt ab, das von der mit der Annotation
Validate gekennzeichneten Methode zurückgegeben wird, und übergeben es dann an die Validator-Methode, die
Set<ConstraintViolation<Object>>
- kurz gesagt - eine Reihe von Klassen mit unterschiedlichen Informationen zu validierten Feldern und Fehlern zurückgibt. Wenn keine Fehler vorliegen, ist das Set leer. Dann gehen wir einfach die Menge durch und erstellen eine Fehlermeldung, wobei alle Felder nicht validiert sind, und werfen die Ausführung.
violation.getPropertyPath() - violation.getMessage() - ,
Fazit
Auf diese Weise können wir die Validierung aller Objekte aufrufen, die wir an einem beliebigen Punkt in der Anwendung benötigen, und bei Bedarf die Annotation und den Aspekt ergänzen, sodass die Validierung nicht nur für Methoden, die ein Objekt zurückgeben, sondern auch für Felder und Parameter von Methoden erfolgreich ist.
PS
Wenn Sie eine mit
Validate gekennzeichnete Methode von einer anderen Methode derselben Klasse
aufrufen , denken Sie an die Verbindung zwischen
aop und proxy .