Aangepaste constraint-annotaties
Maak een aangepaste annotatie @UniqueEmail met een ConstraintValidator-implementatie.
Aangepaste constraint-annotaties is een gratis Java Academy-les op CoddyKit. Dit is les 2 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Java Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Java Academy bevat in totaal 4 lessen.
Wanneer standaardbeperkingen niet volstaan
Standaardannotaties van Bean Validation dekken veelvoorkomende gevallen. Maak voor domeinspecifieke regels (bijvoorbeeld een uniek e-mailadres, een geldig IBAN of de sterkte van een wachtwoord) aangepaste annotaties voor validatiebeperkingen.
De annotatie voor de validatiebeperking definiëren
Maak een annotatie met @Constraint(validatedBy = ...), de vereiste elementen message, groups en payload, en de juiste retentie en het juiste doel.
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 implementeren
Implementeer ConstraintValidator<UniqueEmail, String>. De methode initialize leest de elementen van de annotatie; isValid voert de daadwerkelijke controle uit.
@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);
}
}De aangepaste validatiebeperking gebruiken
Pas de annotatie net als elke standaardbeperking toe op een veld, parameter of retourwaarde.
public record CreateUserRequest(
@NotBlank
String name,
@NotBlank @Email @UniqueEmail
String email
) {}Aangepast bericht met interpolatie
Verwijs in het bericht naar annotatie-elementen met {elementName}. Gebruik ctx.buildConstraintViolationWithTemplate() om aangepaste berichten met dynamische gegevens toe te voegen.
@Constraint(validatedBy = RangeValidator.class)
public @interface InRange {
int min() default 0;
int max() default 100;
String message() default "Must be between {min} and {max}";
// ...
}Beperking op klasseniveau
Pas een beperking toe op klasseniveau om meerdere velden samen te valideren — nuttig voor regels tussen velden, zoals het bevestigen van een wachtwoord.
@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 {};
}Implementatie van een validator op klasseniveau
De validator ontvangt het volledige object. Gebruik meerdere velden om validatie tussen velden uit te voeren.
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;
}
}Validatiebeperkingen combineren
Maak een metabeperking door je aangepaste annotatie te annoteren met bestaande beperkingen. Beide worden automatisch toegepast.
@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 {};
}Meerdere validatiefouten teruggeven
Gebruik ctx.disableDefaultConstraintViolation() en voeg voor elk gevonden probleem afzonderlijke foutmeldingen toe tijdens één validatieronde.
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;
}Door Spring beheerde validators
Omdat UniqueEmailValidator is geannoteerd met @Component, injecteert Spring repositories in deze validator. Dit werkt alleen als de validator via de validator van Spring wordt geïnitialiseerd, wat Spring Boot automatisch configureert.
Aangepaste validators testen
Test validators rechtstreeks met eenheidstests — voor pure validatielogica is geen Spring-context nodig. Gebruik Validation.buildDefaultValidatorFactory() voor integratietests.
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
CreateUserRequest req = new CreateUserRequest("", "bad-email", null);
Set<ConstraintViolation<CreateUserRequest>> violations = validator.validate(req);
System.out.println(violations.size()); // 3Korte controle
Welke interface implementeert een validator voor een aangepaste validatiebeperking?
Samenvatting
Maak een @interface met @Constraint(validatedBy=...). Implementeer ConstraintValidator. Gebruik @Component voor injectie door Spring. Beperkingen op klasseniveau valideren meerdere velden samen. Combineer bestaande beperkingen om duplicatie te voorkomen.
Leer Java met een AI-tutor — gratis
Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.
- Cursussen
- 104
- Lessen
- 374
Veelgestelde vragen
Is de les “Aangepaste constraint-annotaties” gratis?
Ja — de volledige tekst van “Aangepaste constraint-annotaties” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus Java Academy wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus Java Academy bevat in totaal 4 lessen.
Wat leer ik in “Aangepaste constraint-annotaties”?
Maak een aangepaste annotatie @UniqueEmail met een ConstraintValidator-implementatie. Je oefent met Java Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.
Heb ik ervaring nodig om met Java Academy te beginnen?
Ervaring vooraf is niet nodig. Java Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 2 van 4.
Hoe lang duurt de les “Aangepaste constraint-annotaties”?
De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.
Kan ik code schrijven en uitvoeren in deze les over Java Academy?
Ja. Elke les over Java Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.
Alle lessen in deze cursus
- Bean Validation: @NotNull, @Size, @Pattern
- Aangepaste constraint-annotaties
- Globale exceptionafhandeling met @ControllerAdvice
- RFC 7807 Problem Details en consistente foutreacties