Ograničenja metoda s provjerom valjanosti graha 2.0

1. Pregled

U ovom ćemo članku razgovarati o tome kako definirati i provjeriti ograničenja metode pomoću Bean Validation 2.0 (JSR-380).

U prethodnom članku raspravljali smo o JSR-380 s ugrađenim bilješkama i kako implementirati provjeru svojstva.

Ovdje ćemo se usredotočiti na različite vrste ograničenja metoda kao što su:

  • jednoparametarska ograničenja
  • unakrsni parametar
  • povratna ograničenja

Također ćemo pogledati kako ručno i automatski provjeriti valjanost ograničenja pomoću Spring Validatora.

Za slijedeće primjere trebaju nam potpuno iste ovisnosti kao u osnovama provjere valjanosti Java Bean-a.

2. Izjava o ograničenjima metode

Započeti, prvo ćemo razgovarati o tome kako deklarirati ograničenja na parametre metode i povratne vrijednosti metoda.

Kao što je već spomenuto, možemo koristiti bilješke iz javax.valifikacija.ograničenja, ali možemo odrediti i prilagođena ograničenja (npr. za prilagođena ograničenja ili ograničenja više parametara).

2.1. Ograničenja s jednim parametrom

Definiranje ograničenja za pojedinačne parametre je jednostavno. Jednostavno moramo dodati bilješke svakom parametru prema potrebi:

javna void createReservation (@NotNull @Future LocalDate begin, @Min (1) int duration, @NotNull kupac) {// ...}

Isto tako, možemo koristiti isti pristup za konstruktore:

kupac javne klase {javni kupac (@Size (min = 5, max = 200) @NotNull String firstName, @Size (min = 5, max = 200) @NotNull String lastName) {this.firstName = firstName; this.lastName = lastName; } // svojstva, dobivači i postavljači}

2.2. Korištenje ograničenja između parametara

U nekim ćemo slučajevima možda trebati potvrditi više vrijednosti odjednom, npr. Dva numerička iznosa su jedan veći od drugog.

Za ove scenarije možemo definirati prilagođena ograničenja više parametara koja mogu ovisiti o dva ili više parametara.

Ograničenja unakrsnih parametara mogu se smatrati provjerom valjanosti metode jednakom ograničenjima na razini klase. Obje bismo mogli koristiti za provedbu provjere valjanosti na temelju nekoliko svojstava.

Razmislimo o jednostavnom primjeru: varijaciji createReservation () metoda iz prethodnog odjeljka uzima dva parametra tipa LocalDate: datum početka i datum završetka.

Slijedom toga, želimo se u to uvjeriti početi je u budućnosti, i kraj je poslije početi. Za razliku od prethodnog primjera, to ne možemo definirati pomoću ograničenja jednog parametra.

Umjesto toga, trebamo ograničenje više parametara.

Za razliku od ograničenja s jednim parametrom, ograničenja unakrsnih parametara deklariraju se na metodi ili konstruktoru:

@ConsistentDateParameters javna praznina createReservation (LocalDate početak, LocalDate kraj, kupac kupac) {// ...}

2.3. Stvaranje višeparametarskih ograničenja

Za provedbu @ConsistentDateParameters ograničenje, trebaju nam dva koraka.

Prvo, trebamo definirati napomenu ograničenja:

@Constraint (validatedBy = ConsistentDateParameterValidator.class) @Target ({METHOD, CONSTRUCTOR}) @Retention (RUNTIME) @Documented public @interface ConsistentDateParameters {String message () default "Datum završetka mora biti nakon datuma početka i oba moraju biti u budućnosti "; Class [] groups () zadani {}; Klasa [] korisni teret () zadana {}; }

Ovdje su ova tri svojstva obavezna za bilješke ograničenja:

  • poruka - vraća zadani ključ za stvaranje poruka o pogreškama, to nam omogućuje upotrebu interpolacije poruka
  • skupine - omogućuje nam da odredimo grupe za provjeru valjanosti za naša ograničenja
  • korisni teret - mogu ga koristiti klijenti Bean Validation API-ja za dodjeljivanje prilagođenih objekata korisnog tereta ograničenju

Za detalje o tome kako definirati prilagođeno ograničenje, pogledajte službenu dokumentaciju.

Nakon toga možemo definirati klasu validatora:

@SupportedValidationTarget (ValidationTarget.PARAMETERS) javna klasa ConsistentDateParameterValidator implementira ConstraintValidator {@Override public boolean isValid (Object [] value, ConstraintValidatorContext context) {if (value [0] == null || value [1] == null || value [1] ; } if (! (value [0] instanceof LocalDate) ||! (value [1] instanceof LocalDate)) {throw new IllegalArgumentException ("Ilegalni potpis metode, očekuju se dva parametra tipa LocalDate."); } return ((LocalDate) value [0]). isAfter (LocalDate.now ()) && ((LocalDate) value [0]). isBefore ((LocalDate) value [1]); }}

Kao što vidimo, isValid () metoda sadrži stvarnu logiku provjere valjanosti. Prvo se pobrinemo da dobijemo dva parametra tipa LocalDate. Nakon toga provjeravamo jesu li oboje u budućnosti i kraj je poslije početi.

Također je važno primijetiti da @SupportedValidationTarget (ValidationTarget.PARAMETRI) bilješka na ConsistentDateParameterValidator razred je potreban. Razlog tome je zato što @ConsistentDateParameter postavlja se na razini metode, ali ograničenja će se primijeniti na parametre metode (a ne na povratnu vrijednost metode, kao što ćemo razmotriti u sljedećem odjeljku).

Napomena: Specifikacija provjere valjanosti zrna preporučuje se razmotriti null-vrijednosti kao valjane. Ako null nije valjana vrijednost, @NotNull-Umjesto toga treba upotrijebiti bilješku.

2.4. Ograničenja povrata vrijednosti

Ponekad ćemo morati provjeriti valjanost objekta jer ga metoda vraća. Za to možemo koristiti ograničenja povratne vrijednosti.

Sljedeći primjer koristi ugrađena ograničenja:

javna klasa ReservationManagement {@NotNull @Size (min = 1) javni popis getAllCustomers () {return null; }}

Za getAllCustomers (), primjenjuju se sljedeća ograničenja:

  • Prvo, vraćeni popis ne smije biti null i mora imati barem jedan unos
  • Nadalje, popis ne smije sadržavati null unosi

2.5. Prilagođena ograničenja povratne vrijednosti

U nekim ćemo slučajevima možda trebati provjeriti i složene objekte:

javna klasa ReservationManagement {@ValidReservation javna rezervacija getReservationsById (int id) {return null; }}

U ovom primjeru, vraćeni Rezervacija objekt mora udovoljavati ograničenjima definiranim @ValidReservation, što ćemo definirati sljedeće.

Opet, prvo moramo definirati anotaciju ograničenja:

@Constraint (validatedBy = ValidReservationValidator.class) @Target ({METHOD, CONSTRUCTOR}) @Retention (RUNTIME) @Dokumentirano javno @interface ValidReservation {String message () default "Datum završetka mora biti nakon datuma početka" + "i oba moraju biti u budućnosti broj sobe mora biti veći od 0 "; Class [] groups () zadani {}; Klasa [] korisni teret () zadana {}; }

Nakon toga definiramo klasu validatora:

javna klasa ValidReservationValidator implementira ConstraintValidator {@Override public boolean isValid (Rezervacija rezervacije, ConstraintValidatorContext context) {if (rezervacije == null) {return true; } if (! (primjer rezervacije Rezervacije)) {baciti novi IllegalArgumentException ("Ilegalni potpis metode," + "očekivani parametar tipa Rezervacija."); } if (rezervacije.getBegin () == null || rezervacije.getEnd () == null || rezervacije.getCustomer () == null) {return false; } return (rezervacije.getBegin (). isAfter (LocalDate.now ()) && reserve.getBegin (). isBefore (reserve.getEnd ()) && reserve.getRoom ()> 0); }}

2.6. Povratna vrijednost u konstruktorima

Kao što smo definirali METODA i KONSTRUKTOR kao cilj unutar našeg ValidReservation sučelje prije, također možemo napomenuti konstruktor Rezervacija za provjeru valjanosti konstruiranih primjeraka:

javna klasa Rezervacija {@ValidReservation javna rezervacija (LocalDate početak, LocalDate kraj, kupac kupac, int soba) {this.begin = begin; ovo.end = kraj; this.customer = kupac; this.room = soba; } // svojstva, dobivači i postavljači}

2.7. Kaskadna provjera valjanosti

Napokon, Bean Validation API omogućuje nam ne samo provjeru pojedinačnih objekata već i grafova objekata, koristeći takozvanu kaskadnu provjeru valjanosti.

Dakle, možemo koristiti @Valid za kaskadnu provjeru valjanosti ako želimo provjeriti složenost objekata. Ovo vrijedi za parametre metode, kao i za povratne vrijednosti.

Pretpostavimo da imamo a Kupac klasa s nekim svojstvima ograničenja:

kupac javne klase {@Size (min = 5, max = 200) private String firstName; @Size (min = 5, max = 200) private String lastName; // konstruktor, getteri i postavljači}

A Rezervacija razred možda ima Kupac svojstvo, kao i daljnja svojstva s ograničenjima:

javna klasa Rezervacija {@Valid kupac privatnog kupca; @ Pozitivna privatna int soba; // daljnja svojstva, konstruktor, getteri i postavljači}

Ako se sada referiramo Rezervacija kao parametar metode, možemo prisiliti rekurzivno provjeravanje svih svojstava:

javna praznina createNewCustomer (@Valid Rezervacija rezervacije) {// ...}

Kao što vidimo, koristimo @Valid na dva mjesta:

  • Na rezervacija-parametar: pokreće provjeru valjanosti Rezervacija-objekt, kada createNewCustomer () Zove se
  • Kako ovdje imamo ugniježđeni graf objekata, moramo dodati i @Valid na kupac-attribute: time pokreće provjeru valjanosti ovog ugniježđenog svojstva

Ovo također radi za metode koje vraćaju objekt tipa Rezervacija:

@Valid public Reservation getReservationById (int id) {return null; }

3. Provjera valjanosti ograničenja metode

Nakon izjave o ograničenjima u prethodnom odjeljku, sada možemo nastaviti s validacijom tih ograničenja. Za to imamo više pristupa.

3.1. Automatska provjera valjanosti s proljećem

Spring Validation pruža integraciju s Hibernate Validatorom.

Napomena: Provjera proljeća temelji se na AOP-u i koristi Spring AOP kao zadanu implementaciju. Stoga provjera valjanosti vrijedi samo za metode, ali ne i za konstruktore.

Ako sada želimo da Proljeće automatski provjeri naša ograničenja, moramo učiniti dvije stvari:

Prvo, zrnu, koje ćemo provjeriti, moramo označiti s @Validirano:

@Validated public class ReservationManagement {public void createReservation (@NotNull @Future LocalDate begin, @Min (1) int duration, @NotNull Customer customer) {// ...} @NotNull @Size (min = 1) javni popis getAllCustomers ( ) {return null; }}

Drugo, moramo pružiti a MethodValidationPostProcessor grah:

@Configuration @ComponentScan ({"org.baeldung.javaxval.methodvalidation.model"}) javna klasa MethodValidationConfig {@Bean public MethodValidationPostProcessor methodValidationPostProcessor () {return new MethodValidationPostProcessor (); }}

Spremnik će sada baciti a javax.validation.ConstraintViolationException, ako je ograničenje prekršeno.

Ako koristimo Spring Boot, spremnik će registrirati a MethodValidationPostProcessor grah za nas dokle god hibernacijski validator je na stazi.

3.2. Automatska provjera valjanosti s CDI-jem (JSR-365)

Od verzije 1.1, provjera valjanosti graha radi s CDI-om (konteksti i ubrizgavanje ovisnosti za Jakarta EE).

Ako se naša aplikacija izvodi u Jakarta EE spremniku, spremnik će automatski provjeriti ograničenja metode u trenutku pozivanja.

3.3. Programska provjera valjanosti

Za ručna provjera valjanosti metode u samostalnoj Java aplikaciji, možemo koristiti javax.validation.executable.ExecutableValidator sučelje.

Primjerak možemo dohvatiti pomoću sljedećeg koda:

Tvornica ValidatorFactory = Validation.buildDefaultValidatorFactory (); ExecutableValidator executableValidator = factory.getValidator (). ForExecutables ();

ExecutableValidator nudi četiri metode:

  • validateParameters () i validateReturnValue () za validaciju metode
  • validateConstructorParameters () i validateConstructorReturnValue () za provjeru konstruktora

Provjera valjanosti parametara naše prve metode createReservation () bi izgledalo ovako:

ReservationManagement objekt = novi ReservationManagement (); Metoda metode = ReservationManagement.class .getMethod ("createReservation", LocalDate.class, int.class, Customer.class); Object [] parameterValues ​​= {LocalDate.now (), 0, null}; Postavi kršenja = executableValidator.validateParameters (objekt, metoda, parameterValues);

Napomena: Službena dokumentacija obeshrabruje pozivanje ovog sučelja izravno iz aplikacijskog koda, ali korištenje putem tehnologije presretanja metoda, poput AOP-a ili proxyja.

U slučaju da vas zanima kako koristiti ExecutableValidator sučelje, možete pogledati službenu dokumentaciju.

4. Zaključak

U ovom smo tutorijalu kratko pogledali kako koristiti ograničenja metoda s Hibernate Validatorom, a razgovarali smo i o nekim novim značajkama JSR-380.

Prvo smo razgovarali o tome kako proglasiti različite vrste ograničenja:

  • Ograničenja pojedinačnih parametara
  • Unakrsni parametar
  • Ograničenja vraćene vrijednosti

Također smo pogledali kako ručno i automatski provjeriti valjanost ograničenja pomoću Spring Validatora.

Kao i uvijek, puni izvorni kod primjera dostupan je na GitHub-u.


$config[zx-auto] not found$config[zx-overlay] not found