Spring Boot 4:n kattava opas · Oppitunti

Mukautettujen rajoiteannotaatioiden rakentaminen

Luokaa uudelleenkäytettäviä mukautettuja validoijia ConstraintValidatorilla toimialuekohtaisen validointilogiikan toteuttamiseen.

Oppitunti 2/413 vaihetta

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ää. FIELD entiteettikentille, PARAMETER metodiparametreille, METHOD getter-metodeille ja TYPE_USE geneerisille tyypeille, kuten List<@ValidUsername String>.
  • @Retention(RUNTIME) — annotaation on säilyttävä ajonaikaan asti, jotta validointimoottori voi lukea sen reflectionin avulla. Tämä on pakollista; SOURCE- tai CLASS-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- ja payload-attribuutit) sekä ConstraintValidator.
  • @Constraint(validatedBy = ...) yhdistää ne toisiinsa; @Retention(RUNTIME) ja @Target määrittävät näkyvyyden ja sijoituspaikan.
  • isValid() sisältää logiikan, ja sen tulisi käsitellä null kelvollisena arvona sekä jättää vastuu @NotNull-annotaatiolle.
  • Lue annotaation parametrit initialize()-metodissa ja rakenna dynaamiset viestit ConstraintValidatorContext-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.

Aloita maksutta

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

  1. Bean Validation -rajoitteet ja rajoiteryhmät
  2. Mukautettujen rajoiteannotaatioiden rakentaminen
  3. Poikkeusten yleinen käsittely @ControllerAdvicella
  4. RFC 7807 Problem Detail -vastaukset
← Takaisin: Spring Boot 4:n kattava opas