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.