自定义校验注解需两步:定义注解(含@constraint、@target、@retention及标准属性)和实现constraintvalidator(含initialize缓存参数、isvalid执行校验逻辑);使用时需配合@valid/@validated触发,并为枚举字符串绑定注册converter避免类型转换异常。

自定义校验注解的核心是两步:定义注解本身 + 实现对应的校验逻辑类。它不是写个注解就完事,关键在 ConstraintValidator 的实现和正确注册。
定义校验注解
用 @interface 声明注解,必须标注 @Constraint(validatedBy = XxxValidator.class),指明由哪个类执行校验:
- 加上
@Target(如FIELD,PARAMETER)明确能加在哪 - 加上
@Retention(RUNTIME)确保运行时可通过反射读取 - 声明属性,比如
String[] values()用于传入允许的枚举值,或Class> enumClass()指定枚举类型 - 提供
message()、groups()、payload()这三个标准属性(JSR-380 要求)
编写校验器(ConstraintValidator)
实现 ConstraintValidator<yourannotation yourtargettype></yourannotation> 接口:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
initialize()方法里可解析注解参数,比如把values()转成Set缓存,避免每次校验都重复构造 -
isValid()是核心逻辑:接收待校验的值(如字符串、整数)和上下文对象,返回true表示合法 - 若需国际化提示,用
context.buildConstraintViolationWithTemplate(...).addConstraintViolation()替代直接返回 false
在 DTO 或参数上使用
注解生效的前提是 Spring 的校验机制被触发:
- 对请求体对象(
@RequestBody),字段上加你的注解,并在 Controller 方法参数前加@Valid - 对路径变量、查询参数等单个参数,需在 Controller 类上加
@Validated,再在参数前加你的注解(如@MyEnum("PENDING", "DONE") String status) - 确保项目已引入
spring-boot-starter-validation,Spring Boot 2.3+ 默认包含
处理枚举字符串绑定异常(关键细节)
如果校验目标是枚举类型,且前端传的是字符串(如 "pending"),默认会因类型转换失败而抛 MethodArgumentTypeMismatchException,校验根本不会执行:
- 必须注册一个
Converter<string yourenum></string>,查不到时返回null(不能抛异常) - 在
WebMvcConfigurer#addFormatters中注册该 Converter - 这样非法值才能绑定为
null,后续@Valid才有机会调用你的校验器判断是否为空或越界










