Replace 50 Lines of If-Checks with a Single @Valid in Spring Boot

This guide shows how Spring Boot’s built‑in validation (using @Valid, @Validated and Jakarta Validation annotations) can eliminate repetitive if‑statements, handle nested objects, support group validation, and be extended with custom constraint annotations for clean, maintainable request parameter checks.

CodeNotes
CodeNotes
CodeNotes
Replace 50 Lines of If-Checks with a Single @Valid in Spring Boot

1. Add the Validation Dependency

For Spring Boot 2.3+ you need to add the spring-boot-starter-validation starter:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

2. Annotate Your DTO

Apply Jakarta Validation constraints directly on fields. Example DTO for a registration request:

@Data
public class RegisterReq {

    @NotBlank(message = "用户名不能为空")
    @Size(min = 3, max = 20, message = "用户名长度 3~20")
    private String username;

    @NotBlank(message = "密码不能为空")
    @Pattern(regexp = "^[A-Za-z0-9]{6,16}$", message = "密码 6~16 位字母数字")
    private String password;

    @Email(message = "邮箱格式不正确")
    private String email;

    @Min(value = 18, message = "未成年人不能注册")
    private Integer age;
}

Common constraints (covers about 90% of cases):

@NotNull – value must not be null

@NotBlank – string not null and trimmed not empty

@NotEmpty – collection/array/string not null and not empty

@Size(min, max) – length or collection size range

@Min / @Max – numeric range

@Pattern – regular‑expression match

@Email – valid email format

@Past / @Future – date constraints

3. Use @Valid in the Controller

@PostMapping("/register")
public Result<Void> register(@RequestBody @Valid RegisterReq req) {
    userService.register(req);
    return Result.ok(null);
}

If validation fails Spring throws MethodArgumentNotValidException, which can be handled globally to return friendly error messages.

4. Validate Nested Objects

When a DTO contains another object, annotate the field with @Valid to trigger validation of the inner object:

@Data
public class OrderReq {
    @NotNull
    @Valid // only @Valid triggers nested validation
    private AddressDto address;
}

5. Group Validation for Multiple Scenarios

Define marker interfaces for create and update operations, then apply groups to constraints:

public interface Create {}
public interface Update {}

@NotNull(groups = Update.class, message = "id 不能为空")
private Long id;

@NotBlank(groups = {Create.class, Update.class})
private String name;

Controller methods use @Validated(Create.class) or @Validated(Update.class) to activate the appropriate group.

6. @Valid vs @Validated

Key differences:

Source: @Valid comes from the JSR‑303/JSR‑380 standard (Jakarta Validation); @Validated is a Spring extension.

Package: jakarta.validation.Valid vs org.springframework.validation.annotation.Validated.

Group validation: not supported by @Valid, supported by @Validated.

Nested validation: supported by @Valid, not by @Validated on fields.

Usage in Controller parameters: both work.

Usage in Service method parameters: requires the class to be annotated with @Validated (AOP proxy); otherwise validation is ignored.

Typical scenario selection:

Simple RequestBody validation → use @Valid.

When groups are needed → use @Validated on the method parameter.

Service‑layer validation → annotate the service class with @Validated and the method parameters with @Valid or constraint annotations.

Nested objects → always use @Valid on the field.

7. Custom Validation Annotation (Advanced)

Example: a reusable @Phone annotation to validate Chinese mobile numbers.

Step 1 – Define the annotation

@Constraint(validatedBy = PhoneValidator.class)
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Phone {
    String message() default "手机号格式不正确";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

Step 2 – Implement the validator

public class PhoneValidator implements ConstraintValidator<Phone, String> {
    private static final Pattern PHONE_PATTERN = Pattern.compile("^1[3-9]\d{9}$");

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (value == null) return true; // let @NotBlank handle null
        return PHONE_PATTERN.matcher(value).matches();
    }
}

Step 3 – Apply to a DTO

@Data
public class RegisterReq {
    @NotBlank(message = "手机号不能为空")
    @Phone // works like a built‑in constraint
    private String phone;
}

When the field is empty, @NotBlank reports the error; when non‑empty, @Phone validates the format.

For more flexibility you can add a regexp attribute to the annotation and read it in initialize, allowing callers to override the default pattern (e.g., international phone numbers).

Custom constraints can be created for any business rule, such as @IdCard, @Url, @InEnum, or @UniqueUsername (the latter needs a Spring‑managed validator with @Component and @Autowired repository).

Conclusion

@Valid + constraint annotations eliminate verbose if‑checks.

Use @Valid for nested objects; use @Validated for group validation.

Service‑layer validation requires the class to be annotated with @Validated.

Combine validation exceptions with a global handler for user‑friendly responses.

Encapsulate common rules in custom annotations for team‑wide reuse.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Spring BootCustom AnnotationHibernate Validatorparameter validationgroup validation@Valid
CodeNotes
Written by

CodeNotes

Discuss code and AI, and document daily life and personal growth.

0 followers
Reader feedback

How this landed with the community

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.