Deep Dive into Spring Boot Parameter Validation: Implementation, Custom Annotations, and Internationalization
This article explains how Spring Boot leverages JSR‑380 for declarative request validation, walks through the internal processing chain from RequestResponseBodyMethodProcessor to Hibernate Validator, and demonstrates building custom annotations for enum checks and conditional field validation while supporting multilingual error messages.
Spring Boot adopts the JSR‑380 (Bean Validation 2.0) specification to provide powerful, declarative validation for request parameters. It supports annotation‑based checks, nested object validation, and group validation, and allows developers to extend the mechanism with custom ConstraintValidator implementations and internationalized error messages.
The validation flow starts in RequestResponseBodyMethodProcessor.resolveArgument, which parses @RequestBody arguments. It calls validateIfApplicable(binder, parameter) to detect @Validated or any annotation whose name starts with Valid. If present, the method invokes binder.validate(validationHints), which delegates to LocalValidatorFactoryBean.validate. This class forwards the call to the underlying Hibernate Validator, ultimately executing the ConstraintValidator.isValid() method for each constraint.
To validate enum values that the built‑in constraints cannot cover, the article defines a custom annotation @EnumValue with a linkEnum attribute. The corresponding EnumValueValidator implements ConstraintValidator<EnumValue, Object>, retrieves the enum class, obtains its allowed values via a shared CheckEnumValue interface, and checks whether the supplied value is present. An example GenderEnum implements CheckEnumValue<Integer>, and applying @EnumValue to a gender field results in a 400 response with the message "性别枚举值不对" when an illegal value such as 2 is submitted.
For more complex scenarios where the validity of one field depends on another, the article introduces @CombineNotNull. This annotation carries a SpEL condition expression. Its validator, CombineNotNullValidator, caches parsed expressions in a ConcurrentHashMap<String, Expression>, evaluates the condition against the request body (retrieved via a custom RequestBodyHandlerAdvice that stores the body in the request attributes), and ensures the annotated field is non‑null when the condition is true. Using the annotation on a birthday field with the condition #this.gender == 1 produces a clear error if gender is female but birthday is missing.
Internationalization is handled by placing message bundles under resources, e.g., messages.properties (default) and messages_zh_CN.properties (Chinese). Validation annotations can reference these keys with {key} syntax, and Spring automatically selects the appropriate language based on the request’s Accept-Language header, returning localized error texts such as "用户id不能为空".
By combining the built‑in JSR‑380 features with custom annotations and i18n support, developers can achieve concise, robust, and maintainable validation logic that significantly improves system stability.
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.
Shepherd Advanced Notes
Dedicated to sharing advanced Java technical insights, daily work snippets, and the power of persistent effort.
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.
