Wenn Sie die Eingabe mit "Java" überprüfen möchten, ist dies "Bean Validation". Es ist einfach zu bedienen und bequem, da nur eine Anmerkung hinzugefügt wird: smile :. Erstellen wir nun eine Anmerkung, die prüft, ob der Eigenschaftswert in dem als Argument übergebenen Array von Zeichenfolgen enthalten ist, wie unten gezeigt.
AcceptedStringValues.java
@Documented
@Constraint(validatedBy = {AcceptedStringValuesValidator.class})
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface AcceptedStringValues {
String message() default "{com.neriudon.example.validator.AcceptedStringValues.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
String[] value();
@Target({METHOD, FIELD})
@Retention(RUNTIME)
@Documented
public @interface List {
AcceptedStringValues[] value();
}
}
Validator
prüft, ob die an value ()
der Annotation AcceptedStringValues
übergebene Zeichenfolge den Rückgabewert des mit Annotationen versehenen Felds oder der Methode enthält.
AcceptedStringValuesValidator.java
public class AcceptedStringValuesValidator
implements ConstraintValidator<AcceptedStringValues, String> {
// accepted values array
private String[] validValues;
@Override
public void initialize(AcceptedStringValues constraintAnnotation) {
validValues = constraintAnnotation.value();
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value == null) {
return true;
}
// check to exist value or not in accepted values array
return Arrays.stream(validValues).anyMatch(s -> Objects.equals(value, s));
}
}
Der Testcode sieht aus wie ↓.
ValidationSampleApplicationTests.java
public class ValidationSampleApplicationTests {
private ValidatorFactory validatorFactory;
private Validator validator;
@Before
public void setup() {
validatorFactory = Validation.buildDefaultValidatorFactory();
validator = validatorFactory.getValidator();
}
@Test
public void acceptedStringValuesNormal() throws UnsupportedEncodingException {
AcceptedStringValuesSample sample = new AcceptedStringValuesSample("1");
Set<ConstraintViolation<AcceptedStringValuesSample>> result = validator.validate(sample);
// no error
assertThat(result.isEmpty(), is(true));
}
@Test
public void acceptedStringValuesNg() throws Exception {
AcceptedStringValuesSample sample = new AcceptedStringValuesSample("0");
Set<ConstraintViolation<AcceptedStringValuesSample>> result = validator.validate(sample);
// error
assertThat(result.size(), is(1));
// assert error value and message
result.stream().forEach(r -> {
assertThat(r.getInvalidValue(), is("0"));
assertThat(r.getMessage(), is("not accepted value."));
});
}
private static class AcceptedStringValuesSample {
@AcceptedStringValues({"1", "2", "3", "4", "5"})
private String code;
public AcceptedStringValuesSample(String code) {
this.code = code;
}
}
}
Sie wissen, dass Fehlermeldungen automatisch aufgerufen werden, wenn Sie "ValidationMessages.properties" unter dem Klassenpfad erstellen und die Nachricht mit dem in "message" der Annotation-Klasse angegebenen Wert als Schlüssel festlegen. In diesem Beispiel sieht es wie ↓ aus.
ValidationMessages.properties
com.neriudon.example.validator.AcceptedStringValues.message = not accepted values.
Es mag wie ↑ aussehen, aber wenn die Nachricht behoben ist, kann es für den Benutzer schwierig sein, sie zu verstehen. In "Bean Validation" kann der Eigenschaftswert der Anmerkungsklasse in die Fehlermeldung eingebettet werden. Versuchen Sie daher, den im Wert der Anmerkungsklasse in "{value}" festgelegten Wert als Zeichenfolge auszugeben.
ValidationMessages.properties
com.neriudon.example.validator.AcceptedStringValues.message = not contained accepted values: {value}.
Es wird die Meldung "Nicht akzeptierte Werte enthalten: [1, 2, 3, 4, 5]" angezeigt.
Bean Validation
unterstützt EL-Ausdrücke ab 1.1!
Durch Angabe von $ {validatedValue} können Sie das Objekt einbetten, das den Fehler verursacht hat ...
ValidationMessages.properties
com.neriudon.example.validator.AcceptedStringValues.message = ${validatedValue} is not contained accepted values.
Dies führt zu der Meldung "xxx enthält keine akzeptierten Werte". (XXX ist das Objekt, das den Fehler verursacht hat)
** $ {validatedValue} `gibt das fehlerhafte Objekt jedoch so aus, wie es ist. Verwenden Sie es daher nicht, wenn Sie vertrauliche Informationen wie Kennwörter verarbeiten. ** **.
Nun, das Hauptthema ist von hier. Bisher haben wir uns mit "String" befasst, aber wir werden mit "Integer" eine Annotation mit derselben Funktion erstellen.
AcceptedIntegerValues.java
@Documented
@Constraint(validatedBy = { AcceptedIntegerValuesValidator.class })
@Target({ METHOD, FIELD })
@Retention(RUNTIME)
public @interface AcceptedIntegerValues {
String message() default "{com.neriudon.example.validator.AcceptedIntegerValues.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
int[] value();
@Target({ METHOD, FIELD })
@Retention(RUNTIME)
@Documented
@interface List {
AcceptedIntegerValues[] value();
}
}
AcceptedIntegerValuesValidator.java
public class AcceptedIntegerValuesValidator implements ConstraintValidator<AcceptedIntegerValues, Integer> {
// accepted values array
private Integer[] validValues;
@Override
public void initialize(AcceptedIntegerValues constraintAnnotation) {
validValues = ArrayUtils.toObject(constraintAnnotation.value());
}
@Override
public boolean isValid(Integer value, ConstraintValidatorContext context) {
if (value == null) {
return true;
}
// check to exist value or not in accepted values array
return Arrays.stream(validValues).anyMatch(s -> Objects.equals(value, s));
}
}
Fehlermeldung einstellen ...
ValidationMessages.properties
com.neriudon.example.validator.AcceptedIntegerValues.message = not contained accepted values: {value}.
Testen Sie jetzt
TestCode.java
@Test
public void acceptedIntegerValuesNormal() {
AcceptedIntegerValuesSample sample = new AcceptedIntegerValuesSample(1);
Set<ConstraintViolation<AcceptedIntegerValuesSample>> result = validator.validate(sample);
assertThat(result.isEmpty(), is(true));
}
@Test
public void acceptedIntegerValuesNg() {
AcceptedIntegerValuesSample sample = new AcceptedIntegerValuesSample(0);
Set<ConstraintViolation<AcceptedIntegerValuesSample>> result = validator.validate(sample);
assertThat(result.size(), is(1));
result.stream().forEach(r -> {
assertThat(r.getInvalidValue(), is(0));
});
}
private static class AcceptedIntegerValuesSample {
@AcceptedIntegerValues({ 1, 2, 3, 4, 5 })
private int code;
public AcceptedIntegerValuesSample(int code) {
this.code = code;
}
}
Dann ...
javax.validation.ValidationException: HV000149: An exception occurred during message interpolation
at org.hibernate.validator.internal.engine.ValidationContext.interpolate(ValidationContext.java:477)
at org.hibernate.validator.internal.engine.ValidationContext.createConstraintViolation(ValidationContext.java:322)
at org.hibernate.validator.internal.engine.ValidationContext.lambda$createConstraintViolations$0(ValidationContext.java:279)
at java.util.stream.ReferencePipeline$3$1.accept(Unknown Source)
at java.util.Collections$2.tryAdvance(Unknown Source)
at java.util.Collections$2.forEachRemaining(Unknown Source)
at java.util.stream.AbstractPipeline.copyInto(Unknown Source)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(Unknown Source)
at java.util.stream.AbstractPipeline.evaluate(Unknown Source)
at java.util.stream.ReferencePipeline.collect(Unknown Source)
at org.hibernate.validator.internal.engine.ValidationContext.createConstraintViolations(ValidationContext.java:280)
at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateSingleConstraint(ConstraintTree.java:182)
at org.hibernate.validator.internal.engine.constraintvalidation.SimpleConstraintTree.validateConstraints(SimpleConstraintTree.java:68)
at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java:73)
at org.hibernate.validator.internal.metadata.core.MetaConstraint.doValidateConstraint(MetaConstraint.java:127)
at org.hibernate.validator.internal.metadata.core.MetaConstraint.validateConstraint(MetaConstraint.java:120)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateMetaConstraint(ValidatorImpl.java:533)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForSingleDefaultGroupElement(ValidatorImpl.java:496)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:465)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:430)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:380)
at org.hibernate.validator.internal.engine.ValidatorImpl.validate(ValidatorImpl.java:169)
at com.neriudon.example.ValidationSampleApplicationTests.acceptedIntegerValuesNg(ValidationSampleApplicationTests.java:98)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:73)
at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:83)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)
Caused by: java.lang.ClassCastException: [I cannot be cast to [Ljava.lang.Object;
at org.hibernate.validator.internal.engine.messageinterpolation.ParameterTermResolver.interpolate(ParameterTermResolver.java:30)
at org.hibernate.validator.internal.engine.messageinterpolation.InterpolationTerm.interpolate(InterpolationTerm.java:64)
at org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator.interpolate(ResourceBundleMessageInterpolator.java:76)
at org.hibernate.validator.messageinterpolation.AbstractMessageInterpolator.interpolateExpression(AbstractMessageInterpolator.java:385)
at org.hibernate.validator.messageinterpolation.AbstractMessageInterpolator.interpolateMessage(AbstractMessageInterpolator.java:274)
at org.hibernate.validator.messageinterpolation.AbstractMessageInterpolator.interpolate(AbstractMessageInterpolator.java:220)
at org.hibernate.validator.internal.engine.ValidationContext.interpolate(ValidationContext.java:468)
... 55 more
Etwas ist schief gelaufen: müde :. Es scheint, dass das Casting aus dem Array von "Integer" von "" [Ich kann nicht in [Ljava.lang.Object; `" "fehlgeschlagen ist.
Versuchen wir, es mit einem EL-Ausdruck zu einem String zu machen.
ValidationMessages.properties
com.neriudon.example.validator.AcceptedIntegerValues.message = not contained accepted values: ${value.toString()}.
Als ich es damit getestet habe, habe ich keinen Fehler erhalten, aber es sieht so aus:
not contained accepted values: [I@6e9319f. //Integer[]Auflage
not contained accepted values: [1, 2, 3, 4, 5]. // String[]Auflage
Also konvertieren wir "Integer []" mit "Arrays.toString" in "String".
ValidationMessages.properties
com.neriudon.example.validator.AcceptedIntegerValues.message = not contained accepted values: ${java.util.Arrays.toString(value)}.
Also, wenn Sie es ausführen ...
javax.el.PropertyNotFoundException: ELResolver cannot handle a null base Object with identifier [java]
Es gibt kein Objekt wie Java! Ich habe den Fehler bekommen: enttäuscht_relieved :.
Zurück zum Anfang: [EL-Ausdruck der Fehlermeldung von Hibernate Validator 5](http://docs.jboss.org/hibernate/validator/5.2/reference/en-US/html/ch04.html#section-interpolation- Lesen wir über (mit Nachrichtenausdrücken). Dann ...
The validation engine makes the following objects available in the EL context:
the attribute values of the constraint mapped to the attribute names the currently validated value (property, bean, method parameter etc.) under the name validatedValue a bean mapped to the name formatter exposing the var-arg method format(String format, Object… args) which behaves like java.util.Formatter.format(String format, Object… args).
Wenn Sie es frei übersetzen ...
Die Validierungs-Engine kann die folgenden Objekte in EL-Ausdrücken verwenden.
java.util.Formatter.format (String format, Object… args)
basierte FormatierungMit anderen Worten, nichts anderes kann verwendet werden ...? Selbst wenn Sie sich auf das Beispiel unter dem Link beziehen, haben Sie die von Java bereitgestellte Klasse nicht aufgerufen, um die Nachricht zu verarbeiten. / (^ O ^) \ Nantekotai.
Aber es ist nicht ohne Weg. In den Tipps unter dem Beispiel ist es wie folgt geschrieben.
Only actual constraint attributes can be interpolated using message parameters in the form {attributeName}. When referring to the validated value or custom expression variables added to the interpolation context (see Section 11.9.1, “HibernateConstraintValidatorContext”), an EL expression in the form ${attributeName} must be used.
Wenn Sie es frei übersetzen ...
Wenn Sie den Wert festlegen, den Sie für den Kontext verwenden möchten, können Sie mit $ {}
darauf verweisen!
Und das. Der Satz basiert auf dem in 11.9.1. HibernateConstraintValidatorContext geschriebenen Beispiel. Lass es uns versuchen.
Fügen Sie den Prozess der Konvertierung von "Interger []" in "String" hinzu und speichern Sie ihn im Kontext als "acceptValuesToString" zur Methode "isValid".
AcceptedIntegerValuesValidator.java
@Override
public boolean isValid(Integer value, ConstraintValidatorContext context) {
if (value == null) {
return true;
}
// add acceptedValuesToString variable converted accepted integer values to string
context.unwrap(HibernateConstraintValidatorContext.class).addExpressionVariable("acceptedValuesToString", Arrays.toString(validValues));
// check to exist value or not in accepted values array
return Arrays.stream(validValues).anyMatch(s -> Objects.equals(value, s));
}
Wenn Sie also "$ {acceptValuesToString}" in "ValidationMessages.properties" aufrufen ...
ValidationMessages.properties
com.neriudon.example.validator.AcceptedIntegerValues.message = not contained accepted values: ${acceptedValuesToString}.
Ich habe die Fehlermeldung "nicht akzeptierte Werte enthalten: [1, 2, 3, 4, 5]" erhalten. Ich habe es getan: stecken_out_tongue_closed_eyes :!
In diesem Artikel habe ich Ihnen gezeigt, wie Sie Bean-Validierungsfehlermeldungen erlauben, beliebige Werte aufzurufen. Bei dieser Methode gibt es jedoch zwei Probleme.
Da die Standardvalidierungsfunktion erweitert ist, gibt es kein Problem, wenn Sie sie einzeln entwickeln. Wenn Sie sie jedoch beispielsweise als Bibliothek veröffentlichen, müssen Sie beschreiben, welche Werte in JavaDoc usw. verwendet werden können. ..
~~ Diese Funktion wurde in WARN im Abschnitt HibernateConstraintValidatorContext geschrieben und kann sich in Zukunft ändern. ~~
~~ Wie die Person, die den Artikel geschrieben hat, sagt, sollte diese Funktion nicht zu oft verwendet werden: rollende_Augen :. ~~
In Hibernate Validator 6.0.13.Final wurde die obige Warnung entfernt. War es behoben?
Wenn sich Ihr Projekt für die Verwendung des "Hibernate Validator" entscheidet, ist diese Funktion nützlich (welche).
Recommended Posts