Java Academy · Oppitunti

Mukautetut rajoiteannotaatiot

Luo mukautettu @UniqueEmail-annotaatio ConstraintValidator-toteutuksen avulla.

Oppitunti 2/413 vaihetta

Mukautetut rajoiteannotaatiot on ilmainen Java Academy-oppitunti CoddyKitissä. Tämä on oppitunti 2/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Java Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Java Academy-kurssilla on yhteensä 4 oppituntia.

Kun vakiorajoitteet eivät riitä

Bean Validationin vakioannotaatiot kattavat yleiset käyttötapaukset. Toimialakohtaisia sääntöjä varten, kuten yksilöllisen sähköpostiosoitteen, kelvollisen IBAN-numeron tai salasanan vahvuuden tarkistamiseen, luokaa mukautettuja rajoiteannotaatioita.

Rajoiteannotaation määrittäminen

Luokaa annotaatio, jossa on @Constraint(validatedBy = ...), pakolliset message-, groups- ja payload-elementit sekä asianmukaiset retention- ja target-määritteet.

import jakarta.validation.Constraint;
import jakarta.validation.Payload;
@Documented
@Constraint(validatedBy = UniqueEmailValidator.class)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface UniqueEmail {
    String message() default "Email already registered";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

ConstraintValidator-toteutuksen luominen

Toteuttakaa ConstraintValidator<UniqueEmail, String>. initialize-metodi lukee annotaation elementit, ja isValid suorittaa varsinaisen tarkistuksen.

@Component
public class UniqueEmailValidator implements ConstraintValidator<UniqueEmail, String> {
    @Autowired private UserRepository repo;
    @Override
    public boolean isValid(String email, ConstraintValidatorContext ctx) {
        if (email == null) return true; // let @NotBlank handle null
        return !repo.existsByEmail(email);
    }
}

Mukautetun rajoitteen käyttäminen

Käyttäkää annotaatiota minkä tahansa vakiorajoitteen tapaan kentässä, parametrissa tai palautusarvossa.

public record CreateUserRequest(
    @NotBlank
    String name,
    @NotBlank @Email @UniqueEmail
    String email
) {}

Mukautettu viesti interpoloinnilla

Viitatkaa annotaation elementteihin viestissä käyttämällä muotoa {elementName}. Käyttäkää ctx.buildConstraintViolationWithTemplate()-metodia mukautettujen, dynaamisia tietoja sisältävien viestien lisäämiseen.

@Constraint(validatedBy = RangeValidator.class)
public @interface InRange {
    int min() default 0;
    int max() default 100;
    String message() default "Must be between {min} and {max}";
    // ...
}

Luokkatason rajoite

Käyttäkää rajoitetta luokkatasolla useiden kenttien tarkistamiseen yhdessä. Tämä sopii esimerkiksi salasanan vahvistamisen kaltaisiin kenttien välisiin sääntöihin.

@Documented
@Constraint(validatedBy = PasswordMatchValidator.class)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface PasswordMatch {
    String message() default "Passwords do not match";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

Luokkatason validatorin toteutus

Validatori saa koko olion. Käsitelkää useita kenttiä kenttien välisten sääntöjen tarkistamiseksi.

public class PasswordMatchValidator implements ConstraintValidator<PasswordMatch, ChangePasswordRequest> {
    public boolean isValid(ChangePasswordRequest req, ConstraintValidatorContext ctx) {
        if (req.getNewPassword() == null) return true;
        boolean match = req.getNewPassword().equals(req.getConfirmPassword());
        if (!match) {
            ctx.disableDefaultConstraintViolation();
            ctx.buildConstraintViolationWithTemplate("Passwords do not match")
               .addPropertyNode("confirmPassword").addConstraintViolation();
        }
        return match;
    }
}

Rajoitteiden yhdistäminen

Luokaa metarajoite merkitsemällä mukautettu annotaatio olemassa olevilla rajoitteilla. Molemmat rajoitteet otetaan automaattisesti käyttöön.

@NotBlank
@Email
@Size(max = 255)
@Constraint(validatedBy = {})
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidEmail {
    String message() default "Invalid email";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

Useiden virheiden palauttaminen

Kutsukaa ctx.disableDefaultConstraintViolation()-metodia ja lisätkää jokaisesta löydetystä ongelmasta oma virheviesti yhden validatorin suorituksen aikana.

public boolean isValid(String password, ConstraintValidatorContext ctx) {
    List<String> issues = new ArrayList<>();
    if (password.length() < 8) issues.add("Too short");
    if (!password.matches(".*\\d.*")) issues.add("Must contain a digit");
    if (issues.isEmpty()) return true;
    ctx.disableDefaultConstraintViolation();
    issues.forEach(msg -> ctx.buildConstraintViolationWithTemplate(msg).addConstraintViolation());
    return false;
}

Springin hallinnoimat validatorit

Koska UniqueEmailValidator on merkitty @Component-annotaatiolla, Spring injektoi repositoriot siihen. Tämä toimii vain, jos validator käynnistetään Springin validatorin kautta, minkä Spring Boot kytkee automaattisesti käyttöön.

Mukautettujen validatorien testaaminen

Testatkaa validatorit suoraan yksikkötesteillä — puhtaan validointilogiikan testaamiseen ei tarvita Spring-kontekstia. Käyttäkää Validation.buildDefaultValidatorFactory()-metodia integraatiotesteissä.

Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
CreateUserRequest req = new CreateUserRequest("", "bad-email", null);
Set<ConstraintViolation<CreateUserRequest>> violations = validator.validate(req);
System.out.println(violations.size()); // 3

Pikatarkistus

Minkä rajapinnan mukautettu rajoitevalidatori toteuttaa?

Kertaus

Luokaa @interface, jossa on @Constraint(validatedBy=...). Toteuttakaa ConstraintValidator. Käyttäkää @Component-annotaatiota Spring-injektiota varten. Luokkatason rajoitteet tarkistavat useita kenttiä yhdessä. Yhdistäkää olemassa olevia rajoitteita päällekkäisen koodin välttämiseksi.

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
104
Oppitunnit
374

Usein kysytyt kysymykset

Onko oppitunti ”Mukautetut rajoiteannotaatiot” ilmainen?

Kyllä – oppitunnin ”Mukautetut rajoiteannotaatiot” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Java Academy-kurssin, päivitä CoddyKit PROhon. Java Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Mukautetut rajoiteannotaatiot”?

Luo mukautettu @UniqueEmail-annotaatio ConstraintValidator-toteutuksen avulla. Harjoittelet Java Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Java Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Java Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 2/4.

Kuinka kauan ”Mukautetut rajoiteannotaatiot”-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ä Java Academy-oppitunnilla?

Kyllä. Jokainen Java Academy-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: @NotNull, @Size, @Pattern
  2. Mukautetut rajoiteannotaatiot
  3. Poikkeusten keskitetty käsittely @ControllerAdvice-annotaatiolla
  4. RFC 7807:n ongelmatiedot ja yhdenmukaiset virhevastaustaukset
← Takaisin: Java Academy