Backend Development 16 min read

Comprehensive Guide to Spring Validation: RequestBody, RequestParam, and Advanced Techniques

This article provides a detailed tutorial on using Spring Validation in Spring Boot applications, covering simple and advanced usage such as requestBody and requestParam parameter checks, group validation, nested and collection validation, custom constraints, programmatic validation, fail‑fast mode, and the underlying implementation mechanisms.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Comprehensive Guide to Spring Validation: RequestBody, RequestParam, and Advanced Techniques

Java's Bean Validation (JSR‑303) defines a standard for validating objects, but the implementation is provided by hibernate-validator , which adds annotations like @Email and @Length . Spring Validation is a thin wrapper around Hibernate Validator that enables automatic validation of Spring MVC controller parameters.

Simple Usage

For Spring Boot versions below 2.3.x, the spring-boot-starter-web starter automatically includes hibernate-validator . For newer versions, add the dependency manually:

org.hibernate
hibernate-validator
6.0.1.Final

Controller methods receive parameters either as requestBody (POST/PUT) or requestParam/PathVariable (GET). Both ultimately invoke Hibernate Validator; Spring Validation only adds a layer of abstraction.

requestBody Parameter Validation

Define a DTO with constraint annotations and annotate the method parameter with @Validated (or @Valid ) to trigger automatic validation. Validation failures throw MethodArgumentNotValidException , which Spring converts to a 400 response by default.

@Data
public class UserDTO {
    @NotNull
    @Length(min = 2, max = 10)
    private String userName;
    @NotNull
    @Length(min = 6, max = 20)
    private String account;
    @NotNull
    @Length(min = 6, max = 20)
    private String password;
}

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

requestParam/PathVariable Parameter Validation

Annotate controller classes with @Validated and method parameters with constraints such as @Min or @Length . Validation failures raise ConstraintViolationException .

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

    @GetMapping("getByAccount")
    public Result getByAccount(@Length(min = 6, max = 20) @NotNull String account) {
        // business logic after validation
        return Result.ok();
    }
}

Unified Exception Handling

Handle validation exceptions globally to return a consistent response format, often with HTTP status 200 and a custom business code.

@RestControllerAdvice
public class CommonExceptionHandler {
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public Result handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
        BindingResult bindingResult = ex.getBindingResult();
        StringBuilder sb = new StringBuilder("校验失败:");
        for (FieldError fieldError : bindingResult.getFieldErrors()) {
            sb.append(fieldError.getField()).append(":").append(fieldError.getDefaultMessage()).append(", ");
        }
        return Result.fail(BusinessCode.参数校验失败, sb.toString());
    }

    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public Result handleConstraintViolationException(ConstraintViolationException ex) {
        return Result.fail(BusinessCode.参数校验失败, ex.getMessage());
    }
}

Advanced Usage

Group Validation

Define validation groups to apply different rules for the same DTO in different scenarios (e.g., save vs. update).

@Data
public class UserDTO {
    @Min(value = 10000000000000000L, groups = Update.class)
    private Long userId;
    @NotNull(groups = {Save.class, Update.class})
    @Length(min = 2, max = 10, groups = {Save.class, Update.class})
    private String userName;
    // other fields ...
    public interface Save {}
    public interface Update {}
}

Use the group when validating:

@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

Validate nested objects by annotating the field with @Valid . Collections of objects can also be validated.

@Data
public class UserDTO {
    @Valid
    private Job job;
    // other fields ...
    @Data
    public static class Job {
        @Min(1)
        private Long jobId;
        @NotNull
        @Length(min = 2, max = 10)
        private String jobName;
    }
}

Collection Validation

Wrap a collection in a custom class annotated with @Valid to trigger validation of each element.

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

Custom Validation

Create a custom constraint annotation and its validator to implement complex business rules, such as an encrypted ID format.

@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 context) {
        if (value != null) {
            return PATTERN.matcher(value).find();
        }
        return true;
    }
}

Programmatic Validation

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

@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 after the first constraint violation.

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

@Valid vs @Validated

Both trigger validation; @Validated supports validation groups, while @Valid does not.

Implementation Principles

requestBody Validation Mechanism

The RequestResponseBodyMethodProcessor resolves method arguments, reads the request body, creates a WebDataBinder , and calls validateIfApplicable() , which looks for @Validated or any annotation starting with "Valid" and then invokes binder.validate() . The binder delegates to Hibernate Validator.

Method‑Level Validation Mechanism

Spring registers an AOP advisor for beans annotated with @Validated . The MethodValidationInterceptor intercepts method calls, extracts validation groups, and uses ExecutableValidator (Hibernate Validator) to validate method parameters and return values, throwing ConstraintViolationException on failure.

In summary, both requestBody and method‑level validations ultimately rely on Hibernate Validator; Spring Validation merely provides convenient integration with Spring MVC and AOP.

backendJavaSpringvalidationSpring BootHibernate Validator
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

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.