Master Spring Validation in Spring Boot 2.6: From Basics to Custom Annotations
This guide explains Spring Validation in Spring Boot 2.6, covering its lightweight features, configuration of Bean Validation providers, injection of validators, practical examples, custom annotation creation, method‑level validation, and additional configuration options with clear code samples.
Introduction
Spring Validation is a lightweight data‑validation framework for Java objects, offering a unified API, annotation‑based constraints, nested and group validation, internationalization, and extensibility through custom validators. It integrates with Hibernate Validator by default.
Key Features
Lightweight – focuses solely on validation.
Simple to use – annotation‑driven and easy to maintain.
Flexible rules – supports custom constraints.
Internationalization – provides locale‑specific messages.
Hibernate Validator integration – works seamlessly with other validation frameworks.
Bean Validation Basics
Declare constraints on POJO fields using annotations such as @NotNull , @Size , and @Min :
<code>public class Person {
@NotNull
@Size(max=64)
private String name;
@Min(0)
private int age;
}</code>The Bean Validation engine validates instances against these constraints at runtime.
Configuring a Bean Validation Provider
Spring can expose a javax.validation.ValidatorFactory or javax.validation.Validator as beans. The typical configuration uses LocalValidatorFactoryBean :
<code>import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
@Configuration
public class AppConfig {
@Bean
public LocalValidatorFactoryBean validator() {
return new LocalValidatorFactoryBean();
}
}
</code>Injecting Validators
<code>@Service
public class PersonService {
// Java EE validator
@Resource
private Validator validator;
// Spring validator
@Resource
private org.springframework.validation.Validator springValidator;
}
</code>Simple Validation Example
<code>@Service
public class PersonService {
@Resource
private Validator validator;
@Resource
private org.springframework.validation.Validator springValidator;
public void validate(Person person) {
Set<ConstraintViolation<Person>> violations = validator.validate(person);
violations.forEach(cv -> System.out.println(cv.getMessage()));
System.out.println("----------------------");
BindingResult errors = new MapBindingResult(new HashMap<String, Object>(), "person");
springValidator.validate(person, errors);
if (errors.hasErrors()) {
errors.getAllErrors().forEach(e -> System.out.println(e.getDefaultMessage()));
}
}
}
</code>Test Case
<code>@SpringBootTest
class SpringBootValidationApplicationTests {
@Resource
private PersonService ps;
@Test
public void testValidator() {
Person person = new Person();
person.setAge(-1);
ps.validate(person);
}
}
</code> <code>Minimum value must not be less than 0
must not be null
----------------------
Minimum value must not be less than 0
must not be null</code>Custom Annotation Validation
A custom constraint consists of an annotation marked with @Constraint and a validator implementing ConstraintValidator .
<code>@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PrefixConstraintValidator.class)
public @interface PrefixConstraint {
String value() default "";
String message() default "{validator.prefix.error}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
</code>The validator can inject other beans and contain custom logic:
<code>public class PrefixConstraintValidator implements ConstraintValidator<PrefixConstraint, CharSequence> {
@Resource
private DataService ds;
private String prefix;
@Override
public boolean isValid(CharSequence value, ConstraintValidatorContext context) {
ds.ak();
if (value == null) {
return false;
}
return ((String) value).startsWith(prefix);
}
@Override
public void initialize(PrefixConstraint pc) {
prefix = pc.value();
}
}
</code>Method‑Level Validation
Enable method validation by registering MethodValidationPostProcessor and annotating beans with @Validated :
<code>@Bean
public MethodValidationPostProcessor validationPostProcessor() {
return new MethodValidationPostProcessor();
}
@Service
@Validated
public class PersonService {
@NotNull(message = "Return value cannot be null")
public Person findPerson(@NotEmpty(message = "ID cannot be empty") String id) {
return null;
}
}
</code>The class must carry @Validated for the post‑processor to apply the advice.
Testing Method Validation
The thrown javax.validation.ConstraintViolationException should be handled globally via an exception interceptor.
Other Configuration Options
The default LocalValidatorFactoryBean configuration is sufficient for most cases, but you can customize message interpolation, traversal, and other settings. See the Javadoc for details.
https://docs.spring.io/spring-framework/docs/5.3.11/javadoc-api/org/springframework/validation/beanvalidation/LocalValidatorFactoryBean.html
End of tutorial.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.