如何让Java @NotNull校验违规信息显示其他约束的具体参数值?
问题描述
现有username字段需满足以下约束:
- 非空
- 长度在4-64字符之间
- 匹配正则表达式
[A-Za-z0-9]+
当字段为null时,默认错误消息仅显示must not be null,期望显示完整组合消息:must not be null AND length must be between 4 and 64 characters AND must match "[A-Za-z0-9]+"。
初始代码配置
@NotNull @Length(min = 4, max = 64) @Pattern(regexp = "[A-Za-z0-9]+") String username;
尝试修改后的代码
@NotNull(message = """{ jakarta.validation.constraints.NotNull.message} AND {org.hibernate.validator.constraints.Length.message} AND {jakarta.validation.constraints.Pattern.message}""") @Length(min = 4, max = 64) @Pattern(regexp = "[A-Za-z0-9]+") String username;
遇到的问题
修改后错误消息中的min、max、regexp等参数未被渲染为实际值:
ConstraintViolationImpl{ interpolatedMessage='must not be null AND length must be between {min} and {max} AND must match "{regexp}"', propertyPath=username, rootBeanClass=class app.User, messageTemplate='{jakarta.validation.constraints.NotNull.message} AND {org.hibernate.validator.constraints.Length.message} AND {jakarta.validation.constraints.Pattern.message}'}
如何让错误消息显示这些参数的真实值?
解决方案
消息插值仅会处理当前约束注解的参数,跨注解引用其他约束的消息模板时,不会自动替换其他注解的参数。可以通过以下方式实现需求:
方式一:硬编码参数值到消息中
直接将长度范围和正则表达式写死到@NotNull的消息里,适合参数固定的场景:
@NotNull(message = "must not be null AND length must be between 4 and 64 characters AND must match \"[A-Za-z0-9]+\"") @Length(min = 4, max = 64) @Pattern(regexp = "[A-Za-z0-9]+") String username;
方式二:自定义组合约束注解
若参数需要动态调整,建议自定义整合三个约束的注解,在消息模板中显式引用自定义参数:
- 定义组合注解
@Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @NotNull @Length(min = 4, max = 64) @Pattern(regexp = "[A-Za-z0-9]+") @Constraint(validatedBy = {}) public @interface ValidUsername { String message() default "must not be null AND length must be between {lengthMin} and {lengthMax} characters AND must match \"{patternRegexp}\""; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; // 定义可引用的参数 int lengthMin() default 4; int lengthMax() default 64; String patternRegexp() default "[A-Za-z0-9]+"; }
- 使用自定义注解
@ValidUsername String username;
这种方式可集中管理参数,后续修改约束只需调整注解默认值,无需修改消息模板。
方式三:自定义消息插值器(复杂场景)
若需更灵活的消息处理,可自定义MessageInterpolator实现跨注解参数插值,但该方式复杂度高,仅推荐用于复杂场景。
内容的提问来源于stack exchange,提问作者O1G
相关产品推荐
相关产品推荐

