Elegant Spring Boot Parameter Validation: A P7 Engineer’s Guide
This article walks through Spring Boot’s built‑in parameter validation using JSR‑303/JSR‑380, compares @Valid and @Validated, shows how to configure global exception handling, implement group validation, fast‑fail mode, and custom constraints, and demonstrates both controller‑level and service‑level validation with complete code examples.
Parameter Validation Overview
Spring Boot supports data validation out of the box. The spring-boot-starter-validation module bundles Hibernate Validator, which implements the JSR‑303/JSR‑380 Bean Validation specifications. Validation can be triggered on request DTOs in the controller layer or on method arguments in the service layer.
JSR‑303 Standards and Spring Versions
Different Spring versions ship with different validation standards:
Spring 3.0 – JSR 303 – Hibernate Validator 4 (basic annotations)
Spring 4.0 – JSR 349 – Hibernate Validator 5 (group and method validation)
Spring 5.0+ – JSR 380 – Hibernate Validator 6 (full Bean Validation 2.0 support)
Common Validation Annotations
Typical constraint annotations include @NotNull, @NotBlank, @Min / @Max, @Size, @Email, @Pattern, @Future, and the Hibernate‑specific @URL, @Length, @Range. They are placed on fields or method parameters.
Controller‑Level Validation
Annotate a request DTO with the constraints and add @Validated (or @Valid) on the controller method parameter. Spring MVC’s RequestResponseBodyMethodProcessor creates a WebDataBinder, invokes the validator, and throws MethodArgumentNotValidException if any constraint fails.
@PostMapping("/user/create")
public Result createUser(@Validated @RequestBody UserCreateVO user){
return Result.success("参数校验成功");
}Global Exception Handler
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
public Result handleInvalid(MethodArgumentNotValidException ex){
StringBuilder sb = new StringBuilder();
for (ObjectError err : ex.getBindingResult().getAllErrors()){
sb.append(err.getDefaultMessage());
}
return Result.fail().code(ResultCodeEnum.ARGUMENT_VALID_ERROR.getCode())
.message(sb.toString());
}
}Service‑Level Validation
Place @Validated on the service class. Spring creates a proxy that intercepts method calls via MethodValidationInterceptor. Parameters are validated before execution and return values after execution. Validation failures raise ConstraintViolationException, which can be handled by a separate @RestControllerAdvice.
@Service
@Validated
public class UserService {
public String createUser(@Valid UserCreateVO vo){
return "service 校验通过";
}
}Service Exception Handler Example
@RestControllerAdvice
public class ServiceValidationHandler {
@ExceptionHandler(ConstraintViolationException.class)
public ResponseEntity<ErrorResponse> handle(ConstraintViolationException ex){
List<String> errors = ex.getConstraintViolations().stream()
.map(v -> v.getPropertyPath()+": "+v.getMessage())
.collect(Collectors.toList());
return ResponseEntity.badRequest().body(new ErrorResponse("VALIDATION_FAILED", errors));
}
}Group Validation
Define marker interfaces for different operation groups (e.g., CreateGroup, UpdateGroup) and reference them in the @Validated annotation. Only constraints belonging to the specified group are evaluated.
public interface UserGroup {
interface CreateGroup extends Default {}
interface UpdateGroup extends Default {}
}
@Validated(UserGroup.CreateGroup.class)
public Result create(@RequestBody UserVo vo){ ... }Fast‑Fail Mode
Configure the validator to stop at the first violation, improving performance for large payloads.
@Configuration
public class ValidConfig {
@Bean
public Validator validator(){
return Validation.byProvider(HibernateValidator.class)
.configure()
.failFast(true)
.buildValidatorFactory()
.getValidator();
}
}Custom Constraint Example (Phone Number)
Define a new annotation and its validator to enforce a specific phone‑number pattern.
@Documented
@Retention(RUNTIME)
@Target({FIELD, METHOD, PARAMETER, ANNOTATION_TYPE})
@Constraint(validatedBy = PhoneValidator.class)
public @interface PhoneValid {
String message() default "请填写正确的手机号";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
public class PhoneValidator implements ConstraintValidator<PhoneValid, Object> {
private static final String REGEX = "^(13\\d|14[579]|15[^4\\D]|17[^49\\D]|18\\d)\\d{8}$";
public boolean isValid(Object value, ConstraintValidatorContext ctx){
String phone = String.valueOf(value);
return phone.length()==11 && phone.matches(REGEX);
}
}Apply the custom annotation on a DTO field and the validation will be executed automatically.
public class UserCreateVO {
@PhoneValid(message = "请填写正确的手机号")
private String phone;
}Key Takeaways
Spring Boot’s validation is powered by Hibernate Validator and follows the JSR‑303/380 standards.
Use @Valid for simple request‑body checks and @Validated for group or method‑level validation.
Controller validation runs during request binding; service validation runs via AOP proxies.
Global exception handlers translate validation errors into clear API responses.
Fast‑fail mode and custom constraints allow fine‑grained performance and domain‑specific rules.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Tech Freedom Circle
Crazy Maker Circle (Tech Freedom Architecture Circle): a community of tech enthusiasts, experts, and high‑performance fans. Many top‑level masters, architects, and hobbyists have achieved tech freedom; another wave of go‑getters are hustling hard toward tech freedom.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
