Master Bean Validation in Spring 5: From Basics to Custom Constraints
Learn how to integrate Bean Validation with Spring 5.2.23, configure the validator, inject it, create custom constraints, and enable method‑level validation using MethodValidationPostProcessor, with complete code examples and execution results, including handling of constraint violations and bean registration steps.
Overview
Bean Validation offers a universal way to validate Java applications by declaring constraints on domain model properties. The runtime enforces these constraints. Built‑in constraints are available, and you can define custom ones. Example:
<code>public class User {
@NotEmpty(message = "姓名不能为空")
private String name;
@Min(value = 1, message = "年龄必须大于1")
private Integer age;
}</code>The Bean Validation validator then checks instances of this class. For general API information see https://beanvalidation.org/ and for specific constraints refer to the Hibernate Validator documentation at https://hibernate.org/validator/ .
Configuring the Validation Provider
Spring fully supports the Bean Validation API and allows the validator provider to be configured as a Spring bean. You can expose javax.validation.ValidatorFactory or javax.validation.Validator for injection.
Use LocalValidatorFactoryBean to register the default validator:
<code>import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
@Configuration
public class AppConfig {
@Bean
public LocalValidatorFactoryBean validator() {
return new LocalValidatorFactoryBean();
}
}</code>This basic configuration automatically triggers bean validation initialization. Ensure a Bean Validation provider (e.g., Hibernate Validator) is on the classpath.
Injecting the Validator
LocalValidatorFactoryBean implements javax.validation.ValidatorFactory , javax.validation.Validator , and Spring’s org.springframework.validation.Validator . You can inject any of these interfaces into beans that need validation logic.
Direct injection of the Bean Validation API:
<code>import javax.validation.Validator;
@Service
public class MyService {
@Autowired
private Validator validator;
}</code>Or inject Spring’s org.springframework.validation.Validator :
<code>import org.springframework.validation.Validator;
@Service
public class MyService {
@Autowired
private Validator validator;
}</code>Custom Validation
Define a custom annotation:
<code>@Documented
@Constraint(validatedBy = ValidEmptyConstraintValidator.class)
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
public @interface ValidEmpty {
String message() default "";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}</code>Implement the validation logic:
<code>@Component
@SuppressWarnings("rawtypes")
public class ValidEmptyConstraintValidator implements ConstraintValidator<ValidEmpty, Collection> {
@Override
public boolean isValid(Collection value, ConstraintValidatorContext context) {
return !(value == null || value.isEmpty());
}
}</code>Use the custom constraint on a field:
<code>@ValidEmpty(message = "集合不能为空")
private List<String> list;</code>Method Parameter and Return‑Value Validation
Enable method‑level validation by registering MethodValidationPostProcessor :
<code>@Configuration
public class AppConfig {
@Bean
public MethodValidationPostProcessor validationPostProcessor() {
return new MethodValidationPostProcessor();
}
}</code>Annotate target classes with @Validated and place constraint annotations on method parameters:
<code>public class User {
@NotEmpty(message = "姓名不能为空")
private String name;
private Integer age;
}
@Validated
public class UserService {
public void findById(@NotNull(message = "ID不能为空") Long id) {
// ...
}
}</code>Register the beans and invoke the service:
<code>GenericApplicationContext context = new GenericApplicationContext();
AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(context);
reader.registerBean(MethodValidationPostProcessor.class);
reader.registerBean(UserService.class);
context.refresh();
UserService us = context.getBean(UserService.class);
User user = new User();
us.save(user);
us.findById(null);
context.close();</code>Resulting exception:
<code>Exception in thread "main" javax.validation.ConstraintViolationException: findById.arg0: ID不能为空
at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke(MethodValidationInterceptor.java:120)
...</code>All steps demonstrate how to set up Bean Validation in Spring, inject validators, create custom constraints, and apply method‑level validation.
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.