Welche Konfiguration ist erforderlich, um Anmerkungen von javax.validation.constraints
wie @Size
, @NotNull
usw. zu verwenden? Hier ist mein Code:
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
public class Person {
@NotNull
private String id;
@Size(max = 3)
private String name;
private int age;
public Person(String id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
}
Wenn ich versuche, es in einer anderen Klasse zu verwenden, funktioniert die Überprüfung nicht (d. H. Das Objekt wird ohne Fehler erstellt):
Person P = new Person(null, "Richard3", 8229));
Warum gelten keine Einschränkungen für id
und name
? Was muss ich noch tun?
Damit die JSR-303-Bean-Validierung im Frühling funktioniert, benötigen Sie Folgendes:
<mvc:annotation-driven />
validation-api-1.0.0.GA.jar
(sieht so aus, als hätten Sie das schon)hibernate-validator-4.1.0.Final.jar
@Valid
validieren möchten, und fügen Sie anschließend eine BindingResult
in die Methodensignatur ein, um Fehler zu erfassen. Beispiel:
@RequestMapping("handler.do")
public String myHandler(@Valid @ModelAttribute("form") SomeFormBean myForm, BindingResult result, Model model) {
if(result.hasErrors()) {
...your error handling...
} else {
...your non-error handling....
}
}
Sie sollten Validator verwenden, um zu überprüfen, ob Ihre Klasse gültig ist.
Person person = ....;
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
Set<ConstraintViolation<Person>> violations = validator.validate(person);
Durch wiederholte Verstöße können Sie Verstöße feststellen.
Sie müsste einen Validator anrufendie Entität, wenn Sie sie validieren möchten. Dann erhalten Sie eine Gruppe von ConstraintViolationException, die im Grunde zeigt, für welches Feld/s Ihrer Entität eine Beschränkungsverletzung vorliegt und was genau darin lagVielleicht können Sie auch einen Teil des Codes freigeben, von dem Sie erwarten, dass er Ihre Entität überprüft.
Eine häufig verwendete Technik ist die Validierung in @PrePersist und die Rollback-Transaktion, wenn mehrere Datenänderungen während der Transaktion verwendet werden, oder andere Aktionen, wenn eine Validierungsausnahme abgerufen wird.
Ihr Code sollte so aussehen:
@PrePersist
public void prePersist(SomeEntity someEntity){
Validator validator = Validation.buildDefaultValidatorFactory.getValidator();
Set<ConstraintViolation<SomeEntity>> = validator.validate(someEntity);
//do stuff with them, like notify client what was the wrong field, log them, or, if empty, be happy
}
Sie können auch einfach @NonNull
mit der lombok-Bibliothek verwenden, zumindest für das @NotNull
-Szenario. Weitere Details: https://projectlombok.org/api/lombok/NonNull.html
in meinem Fall hatte ich eine benutzerdefinierte Einschränkung auf Klassenebene, die nicht aufgerufen wurde.
@CustomValidation // not called
public class MyClass {
@Lob
@Column(nullable = false)
private String name;
}
sobald ich meiner Klasse, entweder benutzerdefiniert oder Standard, eine Einschränkung auf Feldebene hinzugefügt habe, begann die Einschränkung auf Klassenebene zu funktionieren.
@CustomValidation // now it works. super.
public class MyClass {
@Lob
@Column(nullable = false)
@NotBlank // adding this made @CustomValidation start working
private String name;
}
scheint mir fehlerhaftes Verhalten zu sein, aber leicht genug, um damit umzugehen, denke ich
Ich komme einige Jahre später hierher und konnte es dank atrain 's Kommentar oben beheben. In meinem Fall fehlte @Valid
in der API, die das Objekt (in meinem Fall ein POJO) erhält, das mit @Size
kommentiert wurde. Es hat das Problem gelöst.
Ich musste not keine zusätzliche Anmerkung hinzufügen, wie @Valid
oder @NotBlank
zu der mit @Size
kommentierten Variable, nur diese Einschränkung in der Variablen und das, was ich in der API erwähnt habe ...
Pojo-Klasse:
...
@Size(min = MIN_LENGTH, max = MAX_LENGTH);
private String exampleVar;
...
API-Klasse:
...
public void exampleApiCall(@RequestBody @Valid PojoObject pojoObject){
...
}
Danke und Prost
für Methodenparameter können Sie Objects.requireNonNull () wie folgt verwenden: test(String str) {
Objects.requireNonNull(str);
}
Dies wird jedoch nur zur Laufzeit geprüft und wirft eine NPE, wenn es null ist. Es ist wie eine Vorabprüfung. Aber das ist vielleicht das, wonach Sie suchen.
@Valid at Service Interface würde also nur für dieses Objekt funktionieren. Wenn Sie weitere Überprüfungen in der Hierarchie des ServiceRequest-Objekts haben, müssen Sie die Validierung möglicherweise explizit auslösen. So habe ich es gemacht:
public class ServiceRequestValidator {
private static Validator validator;
@PostConstruct
public void init(){
validator = Validation.buildDefaultValidatorFactory().getValidator();
}
public static <T> void validate(T t){
Set<ConstraintViolation<T>> errors = validator.validate(t);
if(CollectionUtils.isNotEmpty(errors)){
throw new ConstraintViolationException(errors);
}
}
}
Sie müssen auf Objektebene folgende Anmerkungen haben, wenn Sie die Validierung für dieses Objekt auslösen möchten.
@Valid
@NotNull
Sie müssen @Valid zuzu jeder Mitgliedsvariablenhinzufügen, die auch ein Objekt war, das Validierungsbedingungen enthielt.
Eine gute Antwort von atrain , Aber vielleicht ist es die bessere Lösung, Ausnahmen zu erkennen, die eigenen HandlerExceptionResolver Und catch zu verwenden
@Override
public ModelAndView resolveException(
HttpServletRequest aReq,
HttpServletResponse aRes,
Object aHandler,
Exception anExc
){
// ....
if(anExc instanceof MethodArgumentNotValidException) // do your handle error here
}
Dann können Sie Ihren Handler so sauber wie möglich halten ... Sie benötigen BindingResult, Model und SomeFormBean in myHandlerMethod nicht mehr.