Gibt es eine Implementierung der feldübergreifenden Validierung (oder einer Implementierung durch einen Drittanbieter) in Hibernate Validator 4.x? Wenn nicht, wie lässt sich ein Cross-Field-Validator am saubersten implementieren?
Wie können Sie beispielsweise die API verwenden, um zu überprüfen, ob zwei Bean-Eigenschaften gleich sind (z. B. ob die Überprüfung eines Kennwortfelds mit dem Kennwortüberprüfungsfeld übereinstimmt)?
In Anmerkungen würde ich etwas erwarten wie:
public class MyBean {
@Size(min=6, max=50)
private String pass;
@Equals(property="pass")
private String passVerify;
}
validation
hibernate-validator
bean-validation
Bradhouse
quelle
quelle
Antworten:
Jede Feldbeschränkung sollte durch eine eigene Validator-Annotation behandelt werden. Mit anderen Worten, es wird nicht empfohlen, die Validierungs-Annotation eines Felds mit anderen Feldern zu vergleichen. Die feldübergreifende Validierung sollte auf Klassenebene erfolgen. Darüber hinaus wird in JSR-303, Abschnitt 2.2, die bevorzugte Methode zum Ausdrücken mehrerer Validierungen desselben Typs über eine Liste von Anmerkungen verwendet. Dadurch kann die Fehlermeldung pro Übereinstimmung angegeben werden.
Beispiel: Überprüfen eines allgemeinen Formulars:
Die Anmerkung:
Der Validator:
quelle
context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate()).addNode(secondFieldName).addConstraintViolation().disableDefaultConstraintViolation();
Gibt die Möglichkeit, das richtige Feld hervorzuheben (wenn nur JSF es unterstützen würde).BeanUtils.getProperty
gibt eine Zeichenfolge zurück. Das Beispiel sollte wahrscheinlich verwenden,PropertyUtils.getProperty
welches ein Objekt zurückgibt.Ich schlage Ihnen eine andere mögliche Lösung vor. Vielleicht weniger elegant, aber einfacher!
Die
isValid
Methode wird vom Validator automatisch aufgerufen.quelle
@AssertTrue
Methoden haben wollen? Einige Namenskonventionen gelten?Ich bin überrascht, dass dies nicht sofort verfügbar ist. Hier ist eine mögliche Lösung.
Ich habe einen Validator auf Klassenebene erstellt, nicht die Feldebene, wie in der ursprünglichen Frage beschrieben.
Hier ist der Anmerkungscode:
Und der Validator selbst:
Beachten Sie, dass ich MVEL verwendet habe, um die Eigenschaften des zu validierenden Objekts zu überprüfen. Dies könnte durch die Standardreflexions-APIs ersetzt werden, oder wenn es sich um eine bestimmte Klasse handelt, die Sie validieren, durch die Zugriffsmethoden selbst.
Die Annotation @Matches kann dann wie folgt für eine Bean verwendet werden:
Als Haftungsausschluss habe ich dies in den letzten 5 Minuten geschrieben, daher habe ich wahrscheinlich noch nicht alle Fehler ausgebügelt. Ich werde die Antwort aktualisieren, wenn etwas schief geht.
quelle
Mit Hibernate Validator 4.1.0.Final empfehle ich die Verwendung von @ScriptAssert . Ausgenommen von seinem JavaDoc:
Hinweis: Die Auswertung wird von einer Skript- Engine durchgeführt, die in der Java-VM ausgeführt wird, daher auf der Java-Serverseite und nicht auf der Clientseite, wie in einigen Kommentaren angegeben.
Beispiel:
oder mit kürzerem Alias und null-safe:
oder mit Java 7+ null-safe
Objects.equals()
:Trotzdem ist an einer benutzerdefinierten @ Levels- Lösung für Validator auf Klassenebene nichts auszusetzen .
quelle
Feldübergreifende Validierungen können durch Erstellen benutzerdefinierter Einschränkungen durchgeführt werden.
Beispiel: - Vergleichen Sie die Felder password und verifyPassword der Benutzerinstanz.
CompareStrings
StringComparisonMode
CompareStringsValidator
ConstraintValidatorHelper
Benutzer
Prüfung
Ausgabe
Message:- [Password, ConfirmPassword] must be equal.
Mithilfe der CompareStrings-Validierungsbeschränkung können wir auch mehr als zwei Eigenschaften vergleichen und eine von vier Zeichenfolgenvergleichsmethoden mischen.
ColorChoice
Prüfung
Ausgabe
Message:- Please choose three different colors.
In ähnlicher Weise können wir CompareNumbers, CompareDates usw. für die Validierung von Feldern verwenden.
PS Ich habe diesen Code nicht in einer Produktionsumgebung getestet (obwohl ich ihn in einer Entwicklungsumgebung getestet habe). Betrachten Sie diesen Code daher als Milestone Release. Wenn Sie einen Fehler finden, schreiben Sie bitte einen schönen Kommentar. :) :)
quelle
Ich habe Alberthovens Beispiel (Hibernate-Validator 4.0.2.GA) ausprobiert und erhalte eine ValidationException: „Kommentierte Methoden müssen der JavaBeans-Namenskonvention folgen. match () nicht. “auch. Nachdem ich die Methode von "match" in "isValid" umbenannt habe, funktioniert es.
quelle
Wenn Sie das Spring Framework verwenden, können Sie dafür die Spring Expression Language (SpEL) verwenden. Ich habe eine kleine Bibliothek geschrieben, die einen JSR-303-Validator basierend auf SpEL bereitstellt - das macht feldübergreifende Validierungen zum Kinderspiel! Schauen Sie sich https://github.com/jirutka/validator-spring an .
Dadurch werden Länge und Gleichheit der Kennwortfelder überprüft.
Sie können dies auch leicht ändern, um die Kennwortfelder nur dann zu überprüfen, wenn nicht beide leer sind.
quelle
Ich mag die Idee von Jakub Jirutka , Spring Expression Language zu verwenden. Wenn Sie keine weitere Bibliothek / Abhängigkeit hinzufügen möchten (vorausgesetzt, Sie verwenden Spring bereits), finden Sie hier eine vereinfachte Implementierung seiner Idee.
Die Einschränkung:
Der Validator:
Bewerben Sie sich wie folgt:
quelle
Ich habe nicht den Ruf, die erste Antwort zu kommentieren, wollte aber hinzufügen, dass ich Unit-Tests für die Gewinnerantwort hinzugefügt habe und die folgenden Beobachtungen habe:
quelle
Sehr schöne Lösung Bradhouse. Gibt es eine Möglichkeit, die Annotation @Matches auf mehrere Felder anzuwenden?
BEARBEITEN: Hier ist die Lösung, die ich zur Beantwortung dieser Frage gefunden habe. Ich habe die Einschränkung so geändert, dass sie ein Array anstelle eines einzelnen Werts akzeptiert:
Der Code für die Anmerkung:
Und die Umsetzung:
quelle
Sie müssen es explizit aufrufen. Im obigen Beispiel hat Bradhouse Ihnen alle Schritte zum Schreiben einer benutzerdefinierten Einschränkung gegeben.
Fügen Sie diesen Code Ihrer Anruferklasse hinzu.
im obigen Fall wäre es
quelle
Warum probieren Sie nicht Oval: http://oval.sourceforge.net/
Ich sehe so aus, als würde es OGNL unterstützen, also könnten Sie es vielleicht natürlicher machen
quelle
Ihr seid fantastisch. Wirklich erstaunliche Ideen. Ich mag Alberthovens und McGins am meisten, deshalb habe ich beschlossen, beide Ideen zu kombinieren. Und entwickeln Sie eine generische Lösung für alle Fälle. Hier ist meine vorgeschlagene Lösung.
quelle
Ich habe eine kleine Anpassung in Nickos Lösung vorgenommen, damit es nicht erforderlich ist, die Apache Commons BeanUtils-Bibliothek zu verwenden und sie durch die bereits im Frühjahr verfügbare Lösung zu ersetzen, für diejenigen, die sie verwenden, da ich einfacher sein kann:
quelle
Mit der Frage realisierte Lösung: Zugriff auf ein Feld, das in der Annotationseigenschaft beschrieben ist
Und wie benutzt man es ...? So was:
quelle