使用@NotNull注解约束校验时,能否返回默认消息的键而非消息内容?
如何让@NotNull校验返回消息键而非默认消息内容?
当我们使用@NotNull注解进行约束校验时,系统会自动返回解析后的默认消息内容。以下是@NotNull注解的具体实现代码:
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE }) @Retention(RUNTIME) @Repeatable(List.class) @Documented @Constraint(validatedBy = { }) public @interface NotNull { String message() default "{jakarta.validation.constraints.NotNull.message}"; Class<?>[] groups() default { }; Class<? extends Payload>[] payload() default { }; /** * Defines several {@link NotNull} annotations on the same element. * * @see jakarta.validation.constraints.NotNull */ @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE }) @Retention(RUNTIME) @Documented @interface List { NotNull[] value(); } }
请问是否存在某种方式,让校验返回的是该消息对应的键,即jakarta.validation.constraints.NotNull.message?
解决方案
有两种可行方案可以实现这一需求:
1. 自定义MessageInterpolator(全局生效)
Bean Validation的消息解析逻辑由MessageInterpolator接口控制,我们可以实现该接口,跳过消息解析步骤,直接返回原始的消息键:
import jakarta.validation.MessageInterpolator; import jakarta.validation.MessageInterpolator.Context; import java.util.Locale; public class KeyOnlyMessageInterpolator implements MessageInterpolator { @Override public String interpolate(String messageTemplate, Context context) { // 移除消息模板中的大括号,返回纯键值 return messageTemplate.replace("{", "").replace("}", ""); } @Override public String interpolate(String messageTemplate, Context context, Locale locale) { return interpolate(messageTemplate, context); } }
在Spring Boot环境中,通过配置类替换默认的插值器:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import jakarta.validation.Validation; import jakarta.validation.Validator; import jakarta.validation.ValidatorFactory; @Configuration public class ValidationConfig { @Bean public Validator validator() { ValidatorFactory factory = Validation.byDefaultProvider() .configure() .messageInterpolator(new KeyOnlyMessageInterpolator()) .buildValidatorFactory(); return factory.getValidator(); } }
2. 自定义注解(局部生效)
创建一个替代@NotNull的自定义注解,直接将message默认值设为目标键,且不使用大括号包裹(避免系统解析):
import jakarta.validation.Constraint; import jakarta.validation.Payload; import java.lang.annotation.*; @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Constraint(validatedBy = {}) public @interface NotNullWithKey { String message() default "jakarta.validation.constraints.NotNull.message"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) @Retention(RetentionPolicy.RUNTIME) @Documented @interface List { NotNullWithKey[] value(); } }
使用时将原有代码中的@NotNull替换为@NotNullWithKey即可,适合不需要全局修改校验逻辑的场景。
内容的提问来源于stack exchange,提问作者robert trudel
相关产品推荐
相关产品推荐

