Mukautettujen rajoiteannotaatioiden rakentaminen
Luokaa uudelleenkäytettäviä mukautettuja validoijia ConstraintValidatorilla toimialuekohtaisen validointilogiikan toteuttamiseen.
Mukautettujen rajoiteannotaatioiden rakentaminen on ilmainen Spring Boot 4:n kattava opas-oppitunti CoddyKitissä. Tämä on oppitunti 2/4. Voit lukea tästä oppimispolusta kokonaan mitkä tahansa 3 oppituntia ilmaiseksi — sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä käytännön harjoittelun sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Oppitunti kuuluu Spring Boot 4:n kattava opas-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Spring Boot 4:n kattava opas-kurssilla on yhteensä 4 oppituntia.
Miksi mukautettuja constraint-annotaatioita?
Bean Validation sisältää annotaatioita, kuten @NotNull, @Size ja @Email. Tosielämän sovelluksissa on kuitenkin toimialakohtaisia sääntöjä, joita mikään sisäänrakennettu annotaatio ei kata.
- Käyttäjänimen on oltava pienaakkosina ja 3–20 merkkiä pitkä
- Puhelinnumeron on vastattava oman maan muotoa
- Statuskentän arvon on oltava yksi sallituista enum-arvoista
Sen sijaan, että kirjoittaisitte manuaalisia tarkistuksia jokaiseen controlleriin tai serviceen, voitte rakentaa uudelleenkäytettävän mukautetun constraint-annotaation, joka liittyy samaan validointiputkeen sisäänrakennettujen annotaatioiden kanssa.
Mukautetun constraintin kaksi osaa
Jokaisessa Spring Boot 4:n (joka käyttää Jakarta Bean Validationia) mukautetussa constraintissa on täsmälleen kaksi osaa:
- Annotaatio — se, jonka kirjoitatte kenttään, esimerkiksi
@ValidUsername. Se ilmoittaa metatiedot ja viittaa validaattoriin. - ConstraintValidator — luokka, joka sisältää varsinaisen
isValid()-logiikan.
@Constraint-meta-annotaatio yhdistää nämä toisiinsa. Kun validointi suoritetaan, framework luo validaattoristanne instanssin ja kutsuu isValid()-metodia jokaiselle annotoidulle kentälle.
Annotaation määrittäminen
Mukautetun constraint-annotaation on määritettävä kolme vakioattribuuttia: message, groups ja payload. @Constraint(validatedBy = ...) kytkee sen validaattoriluokkaan.
Huomatkaa, että importit tulevat paketista jakarta.validation, eivät vanhasta paketista javax.validation.
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.*;
@Documented
@Constraint(validatedBy = UsernameValidator.class)
@Target({ ElementType.FIELD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidUsername {
String message() default "invalid username";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}@Target- ja @Retention-annotaatioiden ymmärtäminen
Kaksi meta-annotaatiota määrittää, missä ja milloin constraintia käytetään:
- @Target — missä annotaatiota voidaan käyttää.
FIELDentiteettikentille,PARAMETERmetodiparametreille,METHODgetter-metodeille jaTYPE_USEgeneerisille tyypeille, kutenList<@ValidUsername String>. - @Retention(RUNTIME) — annotaation on säilyttävä ajonaikaan asti, jotta validointimoottori voi lukea sen reflectionin avulla. Tämä on pakollista;
SOURCE- taiCLASS-säilyvyys tekisi constraintista näkymättömän.
ConstraintValidatorin kirjoittaminen
Validaattori toteuttaa rajapinnan ConstraintValidator<A, T>, jossa A on annotaatiotyyppinne ja T validoitavan arvon tyyppi (esimerkiksi String).
isValid()-metodi palauttaa arvon true, jos arvo on kelvollinen. Keskeinen sääntö: käsitelkää null-arvo kelvollisena ja antakaa @NotNull-annotaation käsitellä null-arvot erikseen. Näin jokainen constraint keskittyy yhteen asiaan.
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
public class UsernameValidator
implements ConstraintValidator<ValidUsername, String> {
@Override
public boolean isValid(String value, ConstraintValidatorContext ctx) {
if (value == null) {
return true; // let @NotNull handle null
}
return value.matches("^[a-z0-9_]{3,20}$");
}
}Constraintin käyttäminen
Kun constraint on määritetty, sitä käytetään täsmälleen sisäänrakennetun constraintin tavoin. Sijoittakaa se DTO-kenttään ja yhdistäkää se muihin constraintteihin. Spring arvioi ne kaikki, kun olio validoidaan.
Käyttäkää @NotNull-annotaatiota yhdessä @ValidUsername-annotaation kanssa, koska validaattori sallii tarkoituksella null-arvon.
import jakarta.validation.constraints.NotNull;
public record RegisterRequest(
@NotNull
@ValidUsername(message = "username must be 3-20 lowercase chars")
String username,
@NotNull
String password
) {}Validoinnin käynnistäminen controllerissa
Pyynnön mukana tulevien pyyntörunkojen validoimiseksi merkitkää parametri @Valid-annotaatiolla. Jos jokin constraint epäonnistuu, Spring heittää MethodArgumentNotValidException-poikkeuksen ennen metodirungon suorittamista.
Annotaatiossa määrittämästänne message-viestistä tulee asiakkaalle palautettava virheilmoitus.
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/users")
public class UserController {
@PostMapping("/register")
public String register(@Valid @RequestBody RegisterRequest req) {
return "registered: " + req.username();
}
}Virheviestin mukauttaminen dynaamisesti
Joskus staattinen viesti ei riitä — haluat viestin ilmaisevan, miksi validointi epäonnistui. Poista oletusviesti käytöstä ConstraintValidatorContext-olion avulla ja rakenna mukautettu viesti.
Sinun on ensin kutsuttava disableDefaultConstraintViolation()-metodia ja lisättävä sitten oma virheesi. Muuten molemmat viestit näytetään.
@Override
public boolean isValid(String value, ConstraintValidatorContext ctx) {
if (value == null) return true;
if (value.length() < 3 || value.length() > 20) {
ctx.disableDefaultConstraintViolation();
ctx.buildConstraintViolationWithTemplate(
"username length must be between 3 and 20")
.addConstraintViolation();
return false;
}
return value.matches("^[a-z0-9_]+$");
}Parametrien välittäminen rajoitteelle
Tee rajoitteista määritettäviä lisäämällä annotaatioon attribuutteja. Esimerkiksi @ValidUsername voi hyväksyä vähimmäis- ja enimmäispituuden attribuutit min ja max.
Validaattori lukee nämä initialize()-metodissa, joka suoritetaan kerran ennen isValid()-kutsuja.
public @interface ValidUsername {
String message() default "invalid username";
int min() default 3;
int max() default 20;
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}Parametrien lukeminen initialize()-metodissa
Ylikirjoita initialize()-metodi ja tallenna annotaation attribuuttien arvot kenttiin. Kehys kutsuu sitä kerran kutakin validaattori-instanssia kohden ennen ensimmäistäkään isValid()-kutsua.
Näin yksi validaattoriluokka voi palvella monia erilaisia määrityksiä.
public class UsernameValidator
implements ConstraintValidator<ValidUsername, String> {
private int min;
private int max;
@Override
public void initialize(ValidUsername ann) {
this.min = ann.min();
this.max = ann.max();
}
@Override
public boolean isValid(String value, ConstraintValidatorContext ctx) {
if (value == null) return true;
return value.length() >= min && value.length() <= max
&& value.matches("^[a-z0-9_]+$");
}
}Pelkkä Java: validointilogiikka itsenäisenä
Säännöllinen lauseke ja pituuslogiikka ovat tavallista Java-koodia, jota voit testata ilman kehystä. Tässä sama sääntö on ilmaistu suoritettavana ohjelmana, jotta logiikka voidaan varmistaa ennen sen liittämistä Springiin.
Tämän eristyksen ansiosta validaattorit on helppo testata yksikkötesteillä.
public class Main {
static boolean isValidUsername(String value, int min, int max) {
if (value == null) return true;
return value.length() >= min && value.length() <= max
&& value.matches("^[a-z0-9_]+$");
}
public static void main(String[] args) {
System.out.println(isValidUsername("alice_99", 3, 20)); // true
System.out.println(isValidUsername("Al", 3, 20)); // false
System.out.println(isValidUsername("Bad Name", 3, 20)); // false
System.out.println(isValidUsername(null, 3, 20)); // true
}
}Pikatarkistus
Toteutat mukautetun ConstraintValidator-validaattorin String-kentälle. Kenttä on valinnainen, ja erillinen @NotNull huolehtii jo null-arvojen estämisestä. Mitä isValid()-metodin pitäisi palauttaa, kun arvo on null?
Kertaus
Opit rakentamaan uudelleenkäytettäviä mukautettuja rajoiteannotaatioita Spring Boot 4:ssä:
- Rajoitteessa on kaksi osaa: annotaatio (jossa ovat
message-,groups- japayload-attribuutit) sekä ConstraintValidator. @Constraint(validatedBy = ...)yhdistää ne toisiinsa;@Retention(RUNTIME)ja@Targetmäärittävät näkyvyyden ja sijoituspaikan.isValid()sisältää logiikan, ja sen tulisi käsitellänullkelvollisena arvona sekä jättää vastuu@NotNull-annotaatiolle.- Lue annotaation parametrit
initialize()-metodissa ja rakenna dynaamiset viestitConstraintValidatorContext-olion avulla. - Käytä rajoitetta DTO-kentissä ja käynnistä validointi ohjaimissa
@Valid-annotaatiolla.
Näiden mallien avulla toimialueen säännöt ovat yhdessä testatussa paikassa ja liittyvät saumattomasti Springin validointiputkeen.
Opi Java tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 21
- Oppitunnit
- 84
Usein kysytyt kysymykset
Onko oppitunti ”Mukautettujen rajoiteannotaatioiden rakentaminen” ilmainen?
Kyllä — voit lukea täällä verkossa kokonaan ilmaiseksi mitkä tahansa Spring Boot 4:n kattava opas-oppimispolun 3 oppituntia, myös oppitunnin “Mukautettujen rajoiteannotaatioiden rakentaminen”. Sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä interaktiiviset harjoitukset sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Spring Boot 4:n kattava opas-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”Mukautettujen rajoiteannotaatioiden rakentaminen”?
Luokaa uudelleenkäytettäviä mukautettuja validoijia ConstraintValidatorilla toimialuekohtaisen validointilogiikan toteuttamiseen. Harjoittelet Spring Boot 4:n kattava opas-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni Spring Boot 4:n kattava opas-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin Spring Boot 4:n kattava opas-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 2/4.
Kuinka kauan ”Mukautettujen rajoiteannotaatioiden rakentaminen”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä Spring Boot 4:n kattava opas-oppitunnilla?
Kyllä. Jokainen Spring Boot 4:n kattava opas-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- Bean Validation -rajoitteet ja rajoiteryhmät
- Mukautettujen rajoiteannotaatioiden rakentaminen
- Poikkeusten yleinen käsittely @ControllerAdvicella
- RFC 7807 Problem Detail -vastaukset