When to Use @Validated vs @Valid in Spring Boot: A Complete Guide
This article explains the key differences between Spring's @Validated and @Valid annotations, covering their origins, support for group validation, nested property handling, usage in Spring MVC, practical code examples, custom annotations, and the underlying validation mechanism.
1. Introduction
In the Spring framework, @Validated and @Valid are both used for data validation, but they have important differences.
Source
@Valid is part of the JSR‑303 Bean Validation specification (Jakarta EE) and is defined in the validation‑api package.
Group Validation
@Valid does not support group validation, whereas @Validated does via its groups attribute.
Nested Property Validation
For nested properties, @Valid and @Validated are interchangeable, but group validation on nested properties requires @Validated .
Usage in Spring MVC
Both annotations can be placed on method parameters to trigger validation. To apply validation at the controller‑class level, @Validated must be used.
2. Practical Cases
2.1 Group Validation
When different business scenarios need different validation rules, use @Validated with groups:
<code>@NotEmpty(message = "姓名不能为空", groups = G1.class)
private String name;</code>Define a group interface or class (e.g., G1 ) and apply it in the controller:
<code>public Object save(@Validated({G1.class}) @RequestBody User user,
BindingResult errors) {
// ...
}</code>The value attribute can contain multiple groups. @Valid cannot perform group validation.
2.2 Class‑Level Parameter Validation
To validate method parameters, place @Validated on the controller class:
<code>@RestController
@RequestMapping("/validators")
@Validated
public class ValidatorController {
@GetMapping("get")
public Object get(@NotEmpty(message = "参数name不能为空") String name) {
return name;
}
}</code>Directly annotating parameters works only when the class is annotated with @Validated ; @Valid on the class has no effect.
Why @Validated Is Required
Spring Boot registers a MethodValidationPostProcessor that creates proxies only for beans annotated with @Validated . To make @Valid effective, you can customize this post‑processor:
<code>@Bean
MethodValidationPostProcessor methodValidationPostProcessor() {
MethodValidationPostProcessor processor = new MethodValidationPostProcessor();
processor.setValidatedAnnotationType(Valid.class);
return processor;
}</code>3. Lesser‑Known Secrets
3.1 Custom Annotation
Define a custom annotation and meta‑annotate it with @Validated to enable validation:
<code>@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
@Validated
public @interface PackValid {}
@PostMapping("")
public Object save(@PackValid @RequestBody User user, BindingResult errors) {
// ...
}</code>Replacing @Validated with @Valid on the custom annotation will not work.
3.2 Special‑Named Annotations
Annotations whose simple name starts with Valid are also recognized by Spring’s validation logic:
<code>@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface ValidPack {}
@PostMapping("")
public Object save(@ValidPack @RequestBody User user, BindingResult errors) {
// ...
}</code>3.3 Underlying Principle
The utility class determines validation hints as follows:
<code>public abstract class ValidationAnnotationUtils {
public static Object[] determineValidationHints(Annotation ann) {
if (ann instanceof Validated) {
return ((Validated) ann).value();
}
Class<? extends Annotation> annotationType = ann.annotationType();
if ("javax.validation.Valid".equals(annotationType.getName())) {
return EMPTY_OBJECT_ARRAY;
}
Validated validatedAnn = AnnotationUtils.getAnnotation(ann, Validated.class);
if (validatedAnn != null) {
return validatedAnn.value();
}
if (annotationType.getSimpleName().startsWith("Valid")) {
return convertValidationHints(AnnotationUtils.getValue(ann));
}
return null;
}
}</code>These are the core differences and connections between @Validated and @Valid . In newer Spring versions (e.g., 6.1) you can also control the specific exception type thrown.
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.