Backend Development 11 min read

Elegant Parameter Validation in Spring Using @Validated and Custom Annotations

This article explains how to replace repetitive if‑statements with Spring's @Validated and @Valid annotations, shows how to import validation dependencies, demonstrates creating custom validation annotations and constraint validators, and provides a comprehensive list of built‑in javax.validation constraints for clean and maintainable backend code.

Top Architect
Top Architect
Top Architect
Elegant Parameter Validation in Spring Using @Validated and Custom Annotations

In this tutorial, a senior architect demonstrates a more elegant way to perform parameter validation in Spring applications, moving away from verbose if checks.

Why not use if for validation?

The following code shows a typical controller method that validates a User object with many if statements, making the code bulky and hard to read:

@ApiOperation("新增用户")
@PostMapping("/addUser")
public ResultVo insert(@ApiParam("用户信息实体") @RequestBody User user){
    if(user.getUserName!=null){
        throw new BusinessException("用户名称不能为空");
    }
    if(user.getUserPhone!=null){
        throw new BusinessException("用户电话不能为空");
    }
    if(user.getUserPhone().length()){
        throw new BusinessException("用户电话格式不规范");
    }
    return new ResultVo(userService.insert(user));
}

Spring provides the @Valid and @Validated annotations from the Spring Validation framework to handle such checks automatically.

1. Using @Validated for Elegant Validation

@Valid and @Validated both trigger JSR‑303 validation on controller method parameters. The main differences are:

@Valid : defined in javax.validation.Valid ; can be used on fields, method parameters, and supports nested validation when placed on a field.

@Validated : a Spring‑specific wrapper around @Valid ; supports validation groups, which @Valid does not.

1.1 Adding Validation Dependencies

Include one of the following Maven dependencies in your project:

org.springframework.boot
spring-boot-starter
javax.validation
validation-api
2.0.1.Final
org.hibernate.validator
hibernate-validator

Define validation rules on your entity fields using annotations such as @NotNull , @Size , @Pattern , etc.

1.2 Applying @Validated in Controllers

Annotate the controller method parameter with @Validated . You can also specify a validation group (e.g., addGroup.class ) to apply group‑specific rules:

@ApiOperation("新增用户")
@PostMapping("/addUser")
public ResultVo insert(@ApiParam("用户信息实体") @Validated(addUser.class) @RequestBody User user){
    return new ResultVo(userService.insert(user));
}

The addGroup.class is a marker interface used to differentiate validation groups.

2. Built‑in Constraint Annotations (javax.validation.constraints)

Commonly used constraints include:

@NotNull : value must not be null.

@NotBlank : non‑null, trimmed string length > 0.

@NotEmpty : non‑null and not empty (String, Collection, etc.).

@AssertTrue / @AssertFalse : boolean must be true/false.

@Min / @Max : numeric range.

@DecimalMin / @DecimalMax : BigDecimal range.

@Range : numeric range for various types.

@Past / @Future : date must be in the past/future.

@Size : length of String, array, collection, or map.

@Length : string length between min and max.

@Digits : integer and fraction digits.

@Pattern : regex match.

@Email : valid email format.

3. Creating Custom Validation Annotations

If built‑in constraints do not meet your needs, you can define your own annotation and validator.

3.1 Define the Annotation

/** Custom validation annotation */
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = {ListValueConstraintValidator.class})
public @interface ListValue {
    String message() default "{com.itfuture.e.valid.ListValue.message}";
    Class
[] groups() default {};
    Class
[] payload() default {};
    int[] values() default {};
}

3.2 Implement the Validator

public class ListValueConstraintValidator implements ConstraintValidator
{
    private Set
set = new HashSet<>();
    @Override
    public void initialize(ListValue constraintAnnotation) {
        int[] values = constraintAnnotation.values();
        for (int value : values) {
            set.add(value);
        }
    }
    @Override
    public boolean isValid(Integer integer, ConstraintValidatorContext context) {
        return set.contains(integer);
    }
}

3.3 Use the Custom Annotation

Apply @ListValue(values = {0,1,2}) on a field in your entity, and combine it with @Validated in the controller to trigger the custom check.

With these steps, parameter validation in Spring becomes concise, maintainable, and extensible.

For further reading, the article also provides links to additional resources and open‑source projects.

© The original content is sourced from the author's WeChat public account; all rights belong to the original author.

backendJavaSpringvalidationannotationsCustomValidator
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.