Backend Development 17 min read

Comprehensive Guide to Spring Validation: Parameter Checks, Groups, Nested Objects, Collections, Custom Constraints, and Implementation Details

This article provides a thorough tutorial on using Spring Validation for request parameter checking, covering simple usage, dependency setup, requestBody and requestParam validation, group and nested validation, collection handling, custom constraints, programmatic validation, fail‑fast mode, and the underlying implementation in Spring MVC and Hibernate Validator.

Top Architect
Top Architect
Top Architect
Comprehensive Guide to Spring Validation: Parameter Checks, Groups, Nested Objects, Collections, Custom Constraints, and Implementation Details

Simple Usage

Spring provides the validation-api (JSR‑303) standard for bean validation, while hibernate-validator implements this standard and adds annotations such as @Email and @Length . Spring Validation is a thin wrapper around Hibernate Validator that integrates with Spring MVC for automatic request parameter validation.

Dependency Introduction

If you use Spring Boot version < 2.3.x, the spring-boot-starter-web starter automatically brings in hibernate-validator . For versions >= 2.3.x you need to add the dependency manually:

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.0.1.Final</version>
</dependency>

requestBody Parameter Validation

For POST / PUT requests, define a DTO and annotate it with @Validated (or @Valid ) on the controller method:

@PostMapping("/save")
public Result saveUser(@RequestBody @Validated UserDTO userDTO) {
    // business logic after successful validation
    return Result.ok();
}

If validation fails, Spring throws MethodArgumentNotValidException , which is translated to a 400 Bad Request response.

requestParam / PathVariable Validation

For GET requests, use @RequestParam or @PathVariable with constraint annotations. When many parameters are involved, wrap them in a DTO and annotate the controller class with @Validated :

@GetMapping("{userId}")
public Result detail(@PathVariable("userId") @Min(10000000000000000L) Long userId) {
    // business logic after validation
    return Result.ok();
}

Group Validation

Define validation groups (e.g., Save and Update ) on DTO fields to apply different rules in different scenarios, and specify the group in the controller method:

@PostMapping("/save")
public Result saveUser(@RequestBody @Validated(UserDTO.Save.class) UserDTO userDTO) {
    return Result.ok();
}

@PostMapping("/update")
public Result updateUser(@RequestBody @Validated(UserDTO.Update.class) UserDTO userDTO) {
    return Result.ok();
}

Nested Validation

When a DTO contains another object, annotate the nested field with @Valid so that its constraints are also validated:

@Data
public class UserDTO {
    @NotNull @Length(min = 2, max = 10) private String userName;
    @Valid private Job job; // nested object
}

@Data
public static class Job {
    @Min(1) private Long jobId;
    @NotNull @Length(min = 2, max = 10) private String jobName;
}

Collection Validation

To validate each element of a collection, wrap the list in a custom class annotated with @Valid and @Delegate (requires Lombok >= 1.18.6):

public class ValidationList
implements List
{
    @Delegate @Valid public List
list = new ArrayList<>();
    @Override public String toString() { return list.toString(); }
}

Use it in a controller method:

@PostMapping("/saveList")
public Result saveList(@RequestBody @Validated(UserDTO.Save.class) ValidationList
userList) {
    return Result.ok();
}

Custom Constraint

Create a custom annotation (e.g., @EncryptId ) and implement ConstraintValidator to define the validation logic:

@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
@Retention(RUNTIME)
@Constraint(validatedBy = EncryptIdValidator.class)
public @interface EncryptId {
    String message() default "加密id格式错误";
    Class
[] groups() default {};
    Class
[] payload() default {};
}
public class EncryptIdValidator implements ConstraintValidator
{
    private static final Pattern PATTERN = Pattern.compile("^[a-f\\d]{32,256}$");
    @Override public boolean isValid(String value, ConstraintValidatorContext ctx) {
        if (value != null) {
            return PATTERN.matcher(value).find();
        }
        return true;
    }
}

Programmatic Validation

Inject javax.validation.Validator and call its API directly:

@Autowired private javax.validation.Validator globalValidator;

@PostMapping("/saveWithCodingValidate")
public Result saveWithCodingValidate(@RequestBody UserDTO userDTO) {
    Set
> violations =
        globalValidator.validate(userDTO, UserDTO.Save.class);
    if (!violations.isEmpty()) {
        violations.forEach(v -> System.out.println(v));
    }
    return Result.ok();
}

Fail‑Fast Mode

Configure Hibernate Validator to stop at the first constraint violation:

@Bean
public Validator validator() {
    ValidatorFactory factory = Validation.byProvider(HibernateValidator.class)
        .configure()
        .failFast(true)
        .buildValidatorFactory();
    return factory.getValidator();
}

Implementation Details

Spring MVC’s RequestResponseBodyMethodProcessor reads the request body, creates a WebDataBinder , and invokes binder.validate() . The binder delegates to HibernateValidator via targetValidator.validate() . Method‑level validation is handled by MethodValidationPostProcessor , which registers an AOP advisor that uses MethodValidationInterceptor to call ExecutableValidator.validateParameters() and validateReturnValue() on the underlying Hibernate Validator.

All validation paths ultimately rely on Hibernate Validator; Spring Validation merely provides convenient annotations and integration with the MVC lifecycle.

BackendJavaSpringValidationSpring BootHibernate ValidatorParameter Validation
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

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.