Bygge egendefinerte begrensningsannotasjoner
Opprett gjenbrukbare egendefinerte validatorer med ConstraintValidator for domenespesifikk valideringslogikk.
Bygge egendefinerte begrensningsannotasjoner er en gratis leksjon i Komplett guide til Spring Boot 4 på CoddyKit. Dette er leksjon 2 av 4. Du kan lese valgfritt 3 leksjoner fra denne læringsstien gratis i sin helhet – deretter låser CoddyKit PRO opp alle leksjoner, samt praktisk øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Komplett guide til Spring Boot 4, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Komplett guide til Spring Boot 4 inneholder totalt 4 leksjoner.
Hvorfor egendefinerte begrensninger?
Bean Validation leveres med annotasjoner som @NotNull, @Size og @Email. Men virkelige applikasjoner har dom spesifikke regler som ingen innebygd annotasjon dekker.
- Et brukernavn må bestå av små bokstaver og være 3–20 tegn langt
- Et telefonnummer må følge formatet i landet ditt
- Et statusfelt må være én av verdiene i et tillatt enum-sett
I stedet for å skrive manuelle kontroller i hver controller eller tjeneste kan du bygge en gjenbrukbar egendefinert begrensningsannotasjon som kobles til den samme valideringsflyten som de innebygde annotasjonene.
De to delene i en egendefinert begrensning
Hver egendefinerte begrensning i Spring Boot 4 (som bruker Jakarta Bean Validation) består av nøyaktig to deler:
- Annotasjonen — det du skriver på et felt, for eksempel
@ValidUsername. Den deklarerer metadata og peker på en validator. - ConstraintValidator — en klasse som inneholder selve
isValid()-logikken.
Metaannotasjonen @Constraint kobler de to sammen. Når validering kjøres, oppretter rammeverket validatoren din og kaller isValid() for hvert annoterte felt.
Definere annotasjonen
En egendefinert begrensningsannotasjon må deklarere tre standardattributter: message, groups og payload. @Constraint(validatedBy = ...) kobler den til en validator-klasse.
Merk at importene kommer fra jakarta.validation, ikke det gamle 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 {};
}Forstå @Target og @Retention
To metaannotasjoner styrer hvor og når begrensningen din gjelder:
- @Target — hvor annotasjonen kan plasseres.
FIELDfor entitetsfelter,PARAMETERfor metodeargumenter,METHODfor gettere ogTYPE_USEfor generiske typer somList<@ValidUsername String>. - @Retention(RUNTIME) — annotasjonen må være tilgjengelig under kjøring, slik at valideringsmotoren kan lese den via refleksjon. Dette er obligatorisk; lagring med
SOURCEellerCLASSville gjort begrensningen usynlig.
Skrive ConstraintValidator
Validatoren implementerer ConstraintValidator<A, T>, der A er annotasjonstypen din og T er typen til verdien som valideres (for eksempel String).
Metoden isValid() returnerer true hvis verdien er gyldig. En viktig regel er å behandle null som gyldig og la @NotNull håndtere nullverdier separat. Da holder hver begrensning fokus på ett ansvar.
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}$");
}
}Ta i bruk begrensningen
Når begrensningen er definert, brukes den på nøyaktig samme måte som en innebygd begrensning. Plasser den på et DTO-felt og kombiner den med andre begrensninger. Spring evaluerer alle når objektet valideres.
Bruk @NotNull sammen med @ValidUsername, siden validatoren med hensikt tillater null.
import jakarta.validation.constraints.NotNull;
public record RegisterRequest(
@NotNull
@ValidUsername(message = "username must be 3-20 lowercase chars")
String username,
@NotNull
String password
) {}Utløse validering i en controller
For å validere innkommende forespørselskropper annoterer du parameteren med @Valid. Hvis en begrensning mislykkes, kaster Spring en MethodArgumentNotValidException før metodekroppen kjøres.
message-verdien du angir i annotasjonen, blir feilmeldingen som returneres til klienten.
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();
}
}Tilpasse feilmeldingen dynamisk
Noen ganger er ikke en statisk melding nok – De vil at meldingen skal gjenspeile hvorfor valideringen mislyktes. Bruk ConstraintValidatorContext til å deaktivere standardmeldingen og bygge en egendefinert melding.
De må først kalle disableDefaultConstraintViolation() og deretter legge til Deres egen valideringsfeil. Ellers vises begge meldingene.
@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_]+$");
}Sende parametere til valideringsbegrensningen
Gjør valideringsbegrensninger konfigurerbare ved å legge til attributter i annotasjonen. For eksempel en @ValidUsername som godtar lengdene min og max.
Validatoren leser disse i initialize(), som kjøres én gang før kallene til isValid().
public @interface ValidUsername {
String message() default "invalid username";
int min() default 3;
int max() default 20;
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}Lese parametere i initialize()
Overstyr initialize() for å lagre annotasjonens attributtverdier i felter. Rammeverket kaller metoden én gang per validatorinstans, før alle kall til isValid().
Dette gjør at én valideringsklasse kan brukes med mange ulike konfigurasjoner.
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_]+$");
}
}Ren Java: Valideringslogikken som frittstående kode
Kjerne-logikken for regulære uttrykk og lengde er vanlig Java som De kan teste uten et rammeverk. Her uttrykkes den samme regelen som et kjørbart program, slik at De kan kontrollere logikken før De kobler den til Spring.
Denne isoleringen gjør validatorene enkle å enhetsteste.
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
}
}Hurtigsjekk
De implementerer en egendefinert ConstraintValidator for et String-felt. Feltet er valgfritt, og en separat @NotNull håndterer allerede nullverdier. Hva skal isValid() returnere når verdien er null?
Oppsummering
De har lært å bygge gjenbrukbare, egendefinerte annotasjoner for valideringsbegrensninger i Spring Boot 4:
- En valideringsbegrensning består av to deler: annotasjonen (med
message,groupsogpayload) og en ConstraintValidator. @Constraint(validatedBy = ...)kobler dem sammen.@Retention(RUNTIME)og@Targetstyrer synlighet og plassering.isValid()inneholder logikken og bør behandlenullsom gyldig, slik at@NotNullkan håndtere dette.- Bruk
initialize()til å lese annotasjonsparametere, ogConstraintValidatorContexttil å lage dynamiske meldinger. - Bruk valideringsbegrensningen på DTO-felter, og utløs den med
@Validi kontrollere.
Med disse mønstrene ligger domenereglene på ett testet sted og kobles sømløst inn i Springs valideringspipeline.
Lær deg Java med en AI-veileder – gratis
Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.
- Kurs
- 21
- Leksjoner
- 84
Ofte stilte spørsmål
Er leksjonen «Bygge egendefinerte begrensningsannotasjoner» gratis?
Ja – du kan lese valgfritt 3 av leksjonene i læringsstien Komplett guide til Spring Boot 4, inkludert «Bygge egendefinerte begrensningsannotasjoner», gratis i sin helhet her på nettet. Deretter låser CoddyKit PRO opp alle leksjoner, samt interaktiv øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Kurset i Komplett guide til Spring Boot 4 inneholder totalt 4 leksjoner.
Hva lærer jeg i «Bygge egendefinerte begrensningsannotasjoner»?
Opprett gjenbrukbare egendefinerte validatorer med ConstraintValidator for domenespesifikk valideringslogikk. Du øver på Komplett guide til Spring Boot 4 med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.
Trenger jeg erfaring for å begynne med Komplett guide til Spring Boot 4?
Ingen tidligere erfaring er nødvendig. Komplett guide til Spring Boot 4 på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 2 av 4.
Hvor lang tid tar leksjonen «Bygge egendefinerte begrensningsannotasjoner»?
De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.
Kan jeg skrive og kjøre kode i denne Komplett guide til Spring Boot 4-leksjonen?
Ja. Alle Komplett guide til Spring Boot 4-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.
Alle leksjonene i dette kurset
- Bean Validation-begrensninger og begrensningsgrupper
- Bygge egendefinerte begrensningsannotasjoner
- Global unntakshåndtering med @ControllerAdvice
- Problemsvardetaljer etter RFC 7807