Backend Development 7 min read

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.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
When to Use @Validated vs @Valid in Spring Boot: A Complete Guide

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.

backendJavaValidationSpring BootAnnotations
Spring Full-Stack Practical Cases
Written by

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.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.