Mastering Spring Boot Validation: Annotations, Custom Rules, and Global Error Handling

This article explains how to use Bean Validation in Spring Boot to replace repetitive IF‑ELSE checks with annotation‑driven parameter checks, covers built‑in and Hibernate‑specific constraints, demonstrates custom validators, group validation, and shows how to centralize error responses with a global exception handler.

Programmer DD
Programmer DD
Programmer DD
Mastering Spring Boot Validation: Annotations, Custom Rules, and Global Error Handling

What Is Bean Validation?

Bean Validation is a Java specification for annotation‑based data validation. It has evolved from JSR‑303 (1.0) to JSR‑380 (2.0, completed in August 2017). Spring Boot includes it automatically via the starter-web dependency, so no extra libraries are required.

Built‑In Validation Annotations

@Null

– the annotated element must be null. @NotNull – the annotated element must not be null. @AssertTrue – the annotated element must be true. @AssertFalse – the annotated element must be false. @Min(value) – numeric value must be greater than or equal to the specified minimum. @Max(value) – numeric value must be less than or equal to the specified maximum. @DecimalMin(value) – same as @Min but works with BigDecimal. @DecimalMax(value) – same as @Max but works with BigDecimal. @Size(min, max) – the size of a collection, array, or string must be within the given range. @Digits(integer, fraction) – the annotated number must have the specified integer and fraction length. @Past – the date must be in the past. @Future – the date must be in the future. @Pattern(regexp) – the string must match the given regular expression.

Hibernate Validator Additional Constraints

@Email

– the string must be a valid email address. @Length – the string length must be within the defined range. @NotEmpty – the string, collection, map, or array must not be null and must contain at least one element. @Range – the numeric value must fall within the specified range. @NotBlank – the string must be non‑null, trimmed, and have a length greater than zero.

Important Differences

@NotNull

works on any type; the value cannot be null. @NotEmpty works on String, Map, Collection, or arrays; the value cannot be null and must have a size > 0. @NotBlank is only for String; it cannot be null and trim() must produce a non‑empty string.

Using Validation in a Spring Boot Controller

Create a DTO (e.g., UserDTO) and annotate its fields. Then add @Validated to the controller method signature. Example for non‑empty validation:

@NotBlank(message = "邮箱不能为空")
@NotNull(message = "邮箱不能为空")
@Email(message = "邮箱格式错误")
private String email;

When a request with an empty email field is sent, Spring returns a structured error response such as:

{
  "code": "9999",
  "desc": "邮箱不能为空",
  "data": null
}

Global Exception Handling

Define a class GlobalExceptionHandler annotated with @RestControllerAdvice and add a method to handle MethodArgumentNotValidException:

@ExceptionHandler(MethodArgumentNotValidException.class)
public ReturnVO handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
    log.error(e.getMessage(), e);
    return new ReturnVO().error(e.getBindingResult().getFieldError().getDefaultMessage());
}

This centralizes validation errors and returns a consistent JSON format.

Validating Email and Phone Formats

Use the built‑in @Email annotation for email validation. For phone numbers, combine @Pattern with length constraints:

@NotNull(message = "手机号不能为空")
@NotBlank(message = "手机号不能为空")
@Pattern(regexp = "^[1][3-9][0-9]{9}$", message = "手机号格式有误")
@Max(value = 11, message = "手机号只能为{max}位")
@Min(value = 11, message = "手机号只能为{min}位")
private String mobileNo;

Invalid input yields responses such as:

{
  "code": "9999",
  "desc": "邮箱格式错误",
  "data": null
}

Custom Validation Annotation

Define a custom annotation (e.g., @IdCard) and its validator class IdCardValidator. Apply it to a DTO field just like built‑in constraints:

@NotNull(message = "身份证号不能为空")
@IdCard(message = "身份证不合法")
private String idCardNumber;

Group Validation

Create marker interfaces for groups, for example:

public interface Create extends Default {}
public interface Update extends Default {}

Assign groups to annotations:

@NotBlank(message = "用户姓名不能为空", groups = Create.class)
@NotNull(message = "用户姓名不能为空", groups = Create.class)
private String userName;

@NotBlank(message = "邮箱不能为空", groups = Update.class)
@NotNull(message = "邮箱不能为空", groups = Update.class)
@Email(message = "邮箱格式错误", groups = Update.class)
private String email;

Validate a specific group in the controller:

@PostMapping("/user")
public ReturnVO userRegister(@RequestBody @Validated(Create.class) UserDTO userDTO) {
    return userService.userRegister(userDTO);
}

When the userName is empty, the response is:

{
  "code": "9999",
  "desc": "用户姓名不能为空",
  "data": null
}

Single‑Parameter Validation

Validate a single request parameter by annotating it and adding @Validated on the controller class:

@PostMapping("/get")
public ReturnVO getUserInfo(@RequestParam("userId") @NotNull(message = "用户ID不能为空") String userId) {
    return new ReturnVO().success();
}

These techniques eliminate repetitive manual checks, provide clear error messages, and keep controller code concise.

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.

JavaException HandlingBean ValidationSpring BootannotationValidator
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

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.