Metódus-kényszerek babellenőrzéssel 2.0

1. Áttekintés

Ebben a cikkben megvitatjuk, hogyan definiálhatók és érvényesíthetők a módszer korlátai a Bean Validation 2.0 (JSR-380) használatával.

Az előző cikkben megvitattuk a JSR-380-t a beépített kommentárokkal és a tulajdonságok érvényesítésének végrehajtásáról.

Itt a különböző módszer-korlátozásokra fogunk összpontosítani, például:

  • egyparaméteres korlátozások
  • keresztparaméter
  • visszatérési korlátok

Azt is megnézzük, hogyan lehet manuálisan és automatikusan érvényesíteni a megszorításokat a Spring Validator segítségével.

A következő példákhoz pontosan ugyanazokra a függőségekre van szükségünk, mint a Java Bean Validation Basics programban.

2. Nyilatkozat a módszer korlátozásairól

A kezdéshez Először megvitatjuk, hogyan lehet deklarálni a módszer paramétereinek és a módszerek visszatérési értékeinek korlátozásait.

Mint korábban említettük, használhatunk a (z) feliratokat javax.validation.constraints, de megadhatunk egyéni megszorításokat is (például egyedi korlátozások vagy keresztparaméter-korlátozások esetén).

2.1. Egyparaméteres korlátozások

Az egyes paraméterekre vonatkozó korlátozások meghatározása egyszerű. Egyszerűen fel kell tennünk kommentárokat az egyes paraméterekhez, szükség szerint:

public void createReservation (@NotNull @Future LocalDate kezdődik, @Min (1) int időtartam, @NotNull ügyfél ügyfél) {// ...}

Hasonlóképpen, ugyanazt a megközelítést alkalmazhatjuk a kivitelezők számára is:

public class Ügyfél {public Customer (@Size (min = 5, max = 200) @NotNull String firstName, @Size (min = 5, max = 200) @NotNull String vezetékNév) {this.firstName = keresztnév; this.lastName = vezetékNév; } // tulajdonságok, mérőeszközök és beállítók}

2.2. Keresztparaméteres korlátozások használata

Bizonyos esetekben egyszerre több értéket is érvényesítenünk kell, például két numerikus összeg nagyobb, mint a másik.

Ezekhez a forgatókönyvekhez meghatározhatunk egyedi keresztparaméter-korlátozásokat, amelyek két vagy több paramétertől függhetnek.

A paraméterek közötti korlátozások az osztály szintű korlátozásokkal egyenértékű módszer validálásnak tekinthetők. Mindkettőt felhasználhatnánk több tulajdonság alapján történő érvényesítés megvalósítására.

Gondoljunk csak egy egyszerű példára: a createReservation () módszer az előző szakaszból két típusú paramétert vesz fel LocalDate: kezdési és befejezési dátum.

Következésképpen ezt meg akarjuk győződni kezdődik a jövőben van, és vége utána van kezdődik. Az előző példával ellentétben ezt nem definiálhatjuk egyetlen paraméter-korlátozással.

Ehelyett szükségünk van egy keresztparaméter-korlátozásra.

Az egyparaméteres korlátokkal szemben keresztmetszetű paraméterek megszorításait deklaráljuk a metóduson vagy a konstruktoron:

@ConsistentDateParameters public void createReservation (LocalDate begin, LocalDate end, Customer customer) {// ...}

2.3. Keresztparaméteres korlátozások létrehozása

A @ConsistentDateParameters korlátozás, két lépésre van szükségünk.

Először is meg kell definiálja a kényszer annotációját:

@Constraint (validatedBy = ConsistentDateParameterValidator.class) @Target ({METHOD, CONSTRUCTOR}) @Retention (RUNTIME) @Documented public @interface ConsistentDateParameters {String message () alapértelmezett "A befejezés dátumának meg kell lennie a kezdési dátumnak, és mindkettőnek a jövőben kell lennie "; Osztály [] csoportok () alapértelmezett {}; Class [] hasznos teher () alapértelmezett {}; }

Itt ez a három tulajdonság kötelező a kényszerjegyzetekhez:

  • üzenet - visszaadja az alapértelmezett kulcsot a hibaüzenetek létrehozásához, ez lehetővé teszi számunkra az üzenetinterpoláció használatát
  • csoportok - lehetővé teszi számunkra, hogy érvényesítési csoportokat adjunk meg korlátozásainkhoz
  • hasznos teher - a Bean Validation API ügyfelei felhasználhatják az egyedi hasznos teher objektumok korlátozáshoz rendelését

Az egyéni kényszer definiálásával kapcsolatos részletekért tekintse meg a hivatalos dokumentációt.

Ezt követően meghatározhatjuk a validátor osztályt:

@SupportedValidationTarget (ValidationTarget.PARAMETERS) public class ConsistentDateParameterValidator implementálja a ConstraintValidator {@Override public boolean isValid (Object [] value, ConstraintValidatorContext context) {if (value [0] == true = return || érték [1] ; } if (! (a LocalDate értéke [0] instanceof LocalDate értéke) ||! (a LocalDate értéke [1] instanceof példánya)) {dobjon új IllegalArgumentException ("Illegális metódus aláírás, két LocalDate típusú paraméter várható."); } return ((LocalDate) érték [0]). isAfter (LocalDate.now ()) && ((LocalDate) érték [0]). isBefore ((LocalDate) érték [1]); }}

Mint láthatjuk, a érvényes() metódus tartalmazza a tényleges érvényesítési logikát. Először meg kell győződnünk arról, hogy két típusú paramétert kapunk LocalDate. Ezt követően ellenőrizzük, hogy mindkettő a jövőben van-e és vége utána van kezdődik.

Fontos észrevenni, hogy a @SupportedValidationTarget (ValidationTarget.PARAMÉTEREK) kommentár a ConsistentDateParameterValidator osztály szükséges. Ennek oka az, hogy @ConsistentDateParameter metódusszinten van beállítva, de a megszorításokat a metódus paramétereire kell alkalmazni (és nem a módszer visszatérő értékére, amint azt a következő szakaszban tárgyaljuk).

Megjegyzés: a Bean Validation specifikáció megfontolandó nulla-értékek érvényesnek. Ha nulla nem érvényes érték, a @Nem nulla-jegyzetet kell használni helyette.

2.4. Visszatérési korlátok

Néha ellenőriznünk kell egy objektumot, mivel azt egy módszer visszaadja. Ehhez használhatunk visszatérési érték korlátozásokat.

A következő példa beépített korlátozásokat használ:

public class ReservationManagement {@NotNull @Size (min = 1) public list getAllCustomers () {return null; }}

Mert getAllCustomers (), a következő korlátozások érvényesek:

  • Először is, a visszaküldött lista nem lehet nulla és legalább egy bejegyzéssel kell rendelkeznie
  • Továbbá a lista nem tartalmazhat nulla bejegyzés

2.5. Visszatérési érték egyéni korlátozások

Bizonyos esetekben összetett objektumok érvényesítésére is szükségünk lehet:

public class ReservationManagement {@ValidReservation public Reservation getReservationsById (int id) {return null; }}

Ebben a példában egy visszaküldött Foglalás objektumnak meg kell felelnie a @ValidReservation, amelyet legközelebb meghatározunk.

Újra, először meg kell határoznunk a kényszer annotációját:

@Constraint (validatedBy = ValidReservationValidator.class) @Target ({METHOD, CONSTRUCTOR}) @Retention (RUNTIME) @Documented public @interface ValidReservation {String message () alapértelmezett "A befejezés dátumának a kezdési dátum után kell lennie" + ", és mindkettőnek meg kell lennie a jövőben a szoba számának nagyobbnak kell lennie, mint 0 "; Osztály [] csoportok () alapértelmezett {}; Class [] hasznos teher () alapértelmezett {}; }

Ezt követően meghatározzuk a validátor osztályt:

public class ValidReservationValidator implementálja a ConstraintValidator {@Orride public boolean isValid (Reservation reserve, ConstraintValidatorContext context) {if (reserve == null) {return true; } if (! (Reservation instanceof Reservation)) {dobja be az új IllegalArgumentException szót ("Illegális módszer aláírása," + "a Reservation típus várható paramétere."); } if (foglalás.getBegin () == null || foglalás.getEnd () == null || foglalás.getCustomer () == null) {return false; } return (booking.getBegin (). isAfter (LocalDate.now ()) && booking.getBegin (). isBefore (booking.getEnd ()) && booking.getRoom ()> 0); }}

2.6. Visszatérési érték a kivitelezőknél

Ahogy definiáltuk MÓDSZER és KONSTRUKTŐR mint cél a mi ValidReservation interfész előtt, feljegyezhetjük a Foglalás a felépített példányok érvényesítéséhez:

public class Reservation {@ValidReservation public Reservation (LocalDate begin, LocalDate end, Customer customer, int room) {this.begin = begin; ez.vég = vég; ez.ügyfél = vásárló; ez.szoba = szoba; } // tulajdonságok, getterek és beállítók}

2.7. Lépcsőzetes érvényesítés

Végül a Bean Validation API lehetővé teszi számunkra, hogy az egyes objektumok, hanem az objektumgrafikonok ellenőrzését is elvégezzük, az úgynevezett kaszkádos validálás segítségével.

Ezért használhatjuk @Érvényes lépcsőzetes érvényesítéshez, ha összetett objektumokat akarunk érvényesíteni. Ez a metódus paraméterei mellett a visszatérő értékek esetében is működik.

Tegyük fel, hogy van egy Vevő osztály néhány tulajdonságkorlátozással:

public class Ügyfél {@Size (min = 5, max = 200) private String keresztnév; @Size (min = 5, max = 200) privát karakterlánc vezetéknév; // kivitelező, mérőeszközök és beállítók}

A Foglalás osztálynak lehet egy Vevő tulajdonság, valamint további korlátozásokkal rendelkező tulajdonságok:

nyilvános osztály Foglalás {@Valid private customer customer; @ Pozitív privát int szoba; // további tulajdonságok, konstruktor, mérőeszközök és beállítók}

Ha most hivatkozunk Foglalás mint metódus paraméter, kikényszeríthetjük az összes tulajdonság rekurzív validálását:

public void createNewCustomer (@Valid foglalás foglalás) {// ...}

Mint láthatjuk, használjuk @Érvényes két helyen:

  • A foglalás-parameter: kiváltja a Foglalás-objektum, mikor createNewCustomer () nak, nek hívják
  • Mivel itt van beágyazott objektumgrafikon, hozzá kell adnunk a-t is @Érvényes a vevő-attribute: ezáltal kiváltja ennek a beágyazott tulajdonságnak az érvényesítését

Ez a típusú objektumot visszaadó módszereknél is működik Foglalás:

@Valid public fenntartás getReservationById (int id) {return null; }

3. A módszer korlátozásainak érvényesítése

Az előző szakaszban szereplő korlátozások deklarálása után most folytathatjuk ezeknek a korlátozásoknak a tényleges érvényesítését. Ehhez többféle megközelítésünk van.

3.1. Automatikus ellenőrzés tavasszal

A tavaszi validálás integrációt biztosít a hibernált ellenőrzővel.

Megjegyzés: A Spring Validation az AOP-n alapul, és a Spring AOP-t használja alapértelmezett megvalósításként. Ezért az érvényesítés csak a módszereknél működik, de a konstruktoroknál nem.

Ha most azt akarjuk, hogy a tavasz automatikusan érvényesítse korlátjainkat, két dolgot kell tennünk:

Először is meg kell jelölnünk a babot, amelyet validálni kell @Validated:

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

Másodszor meg kell adnunk a MethodValidationPostProcessor bab:

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

A konténer most a javax.validation.ConstraintViolationException, ha valamely korlátozást megszegnek.

Ha Spring Boot-ot használunk, a konténer regisztrálja a MethodValidationPostProcessor babot nekünk, amíg hibernate-validator osztályúton van.

3.2. Automatikus érvényesítés CDI-vel (JSR-365)

Az 1.1 verziótól kezdve a Bean Validation a CDI-vel (Contexts and Dependency Injection for Jakarta EE) működik.

Ha alkalmazásunk egy Jakarta EE-tárolóban fut, akkor a tároló automatikusan meghívja a metóduskényszereket.

3.3. Programos érvényesítés

Mert kézi módszer validálása önálló Java alkalmazásban, használhatjuk a javax.validation.executable.ExecutableValidator felület.

Egy példányt a következő kód segítségével tudunk lekérni:

ValidatorFactory gyár = Validation.buildDefaultValidatorFactory (); ExecutableValidator végrehajthatóValidator = factory.getValidator (). ForExecutables ();

Az ExecutableValidator négy módszert kínál:

  • validateParameters () és validateReturnValue () a módszer validálásához
  • validateConstructorParameters () és validateConstructorReturnValue () a konstruktor validálásához

Első módszerünk paramétereinek ellenőrzése createReservation () így nézne ki:

ReservationManagement object = new ReservationManagement (); Method módszer = ReservationManagement.class .getMethod ("createReservation", LocalDate.class, int.class, Customer.class); Object [] parameterValues ​​= {LocalDate.now (), 0, null}; Készlet szabálysértések = végrehajthatóValidator.validateParameters (objektum, módszer, paraméterértékek);

Megjegyzés: A hivatalos dokumentáció nem javasolja, hogy ezt az interfészt közvetlenül az alkalmazáskódból hívják meg, hanem egy módszer-lehallgatási technológián keresztül használják, például AOP vagy proxyk.

Abban az esetben, ha érdekelne a ExecutableValidator felületen, akkor megnézheti a hivatalos dokumentációt.

4. Következtetés

Ebben az oktatóanyagban gyorsan áttekinthettük a módszer korlátozásainak használatát a Hibernate Validator alkalmazással, valamint megvitattuk a JSR-380 néhány új funkcióját.

Először megvitattuk, hogyan lehet deklarálni a különböző típusú korlátozásokat:

  • Egy paraméter korlátai
  • Keresztparaméter
  • Visszatérési korlátok

Azt is megvizsgáltuk, hogyan lehet manuálisan és automatikusan érvényesíteni a megszorításokat a Spring Validator segítségével.

Mint mindig, a példák teljes forráskódja elérhető a GitHubon.