
在J*a Bean Validation中,当一个字段被标记为`@NotNull`且同时拥有其他约束(如`@Length`、`@Pattern`)时,如果该字段的值为`null`,默认行为是只触发`@NotNull`约束。这意味着,像`@Length`和`@Pattern`这样的约束通常会将`null`视为有效输入(或者说,它们只在值非`null`时才进行校验),因此它们的错误消息不会被包含在最终的验证结果中。这导致了一个常见问题:当`username`字段为`null`时,我们可能只得到“`must not be null`”的错误提示,而无法得知它还有长度和格式的限制,使得用户体验不佳。
考虑以下username字段的定义:
@NotNull @Length(min = 4, max = 64) @Pattern(regexp = "[A-Za-z0-9]+") String username;
当username为null时,只会生成@NotNull的错误。如果尝试直接在@NotNull的message属性中组合所有约束的模板:
@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})并不会被解析为实际的数值。这是因为这些占位符是其对应约束的属性,而不是@NotNull约束本身的属性。为了解决这个问题,我们需要一种机制来将这些独立的约束及其属性整合到一个统一的验证逻辑和消息模板中。
立即学习“J*a免费学习笔记(深入)”;
解决上述问题的最佳方法是创建一个自定义的复合约束(Composite Constraint)。这种约束本身不包含具体的验证逻辑,而是通过组合其他标准约束来实现复杂的验证规则,并能统一管理错误消息。
首先,创建一个新的注解,例如@ValidUsername,并将其标记为@Constraint。这个注解将包含所有我们希望组合的约束:@NotNull、@Length和@Pattern。
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.ReportAsSingleViolation; // 确保导入正确包
import j*a.lang.annotation.Retention;
import j*a.lang.annotation.Target;
import static j*a.lang.annotation.ElementType.FIELD;
import static j*a.lang.annotation.RetentionPolicy.RUNTIME;
@Constraint(validatedBy = {}) // 无需具体验证器,它将委托给内部约束
@NotNull // 确保非null
@Length(min = 4, max = 64) // 长度约束
@Pattern(regexp = "[A-Za-z0-9]+") // 模式约束
@ReportAsSingleViolation // 关键:将所有内部约束的错误报告为单一错误
@Target(FIELD) // 作用于字段
@Retention(RUNTIME) // 运行时有效
public @interface ValidUsername {
String message() default """
{jakarta.validation.constraints.NotNull.message}
AND {org.hibernate.validator.constraints.Length.message}
AND {jakarta.validation.constraints.Pattern.message}""";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}关键点解释:
尽管我们已经组合了消息模板,但如前所述,{min}、{max}、{regexp}等占位符仍然无法被解析。这是因为它们是@Length和@Pattern的属性,而不是@ValidUsername的属性。为了让Bean Validation框架能够正确解析这些占位符,我们需要在@ValidUsername注解中声明这些属性,并通过@OverridesAttribute注解将它们映射到内部约束。
歌者PPT
歌者PPT,AI 写 PPT 永久免费
358
查看详情
修改@ValidUsername注解,添加min(), max(), regexp()方法:
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.ReportAsSingleViolation;
import org.hibernate.validator.OverridesAttribute; // 确保导入正确包
import j*a.lang.annotation.Retention;
import j*a.lang.annotation.Target;
import static j*a.lang.annotation.ElementType.FIELD;
import static j*a.lang.annotation.RetentionPolicy.RUNTIME;
@Constraint(validatedBy = {})
@NotNull
@Length(min = 4, max = 64)
@Pattern(regexp = "[A-Za-z0-9]+")
@ReportAsSingleViolation
@Target(FIELD)
@Retention(RUNTIME)
public @interface ValidUsername {
// 默认消息模板,包含所有约束的占位符
String message() default """
{jakarta.validation.constraints.NotNull.message}
AND {org.hibernate.validator.constraints.Length.message}
AND {jakarta.validation.constraints.Pattern.message}""";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
// 使用 @OverridesAttribute 将此注解的属性映射到内部约束
@OverridesAttribute(constraint = Length.class, name = "min")
int min() default 4; // 默认值与 @Length 的 min 保持一致
@OverridesAttribute(constraint = Length.class, name = "max")
int max() default 64; // 默认值与 @Length 的 max 保持一致
@OverridesAttribute(constraint = Pattern.class, name = "regexp")
String regexp() default "[A-Za-z0-9]+"; // 默认值与 @Pattern 的 regexp 保持一致
}@OverridesAttribute解释:
Length.class, name = "min"): 这行代码告诉Bean Validation框架,@ValidUsername注解中的min()方法的值应该被用来覆盖@Length约束的min属性。现在,我们只需将原始字段上的所有独立约束替换为我们自定义的@ValidUsername注解即可:
// 假设在一个DTO或实体类中
public class User {
@ValidUsername
private String username;
// ... getter/setter ...
}当username字段为null时,现在将生成类似以下格式的完整错误消息:
must not be null AND length must be between 4 and 64 characters AND must match "[A-Za-z0-9]+"
这大大提升了错误信息的清晰度和用户体验。
@ValidUsername(min = 6, max = 32, regexp = "[a-z0-9]+") private String customUsername;
这将使用customUsername上定义的min、max和regexp值,而不是@ValidUsername注解中的默认值。
通过创建自定义复合约束并巧妙利用@OverridesAttribute,我们可以有效地解决J*a Bean Validation中多约束消息合并和参数解析的难题,从而提供更准确、更友好的验证反馈。
以上就是J*a Bean Validation中合并多条约束消息并解析参数的详细内容,更多请关注其它相关文章!
# 创建一个
# 利用贴吧论坛营销推广
# 嘉祥全网seo优化
# 发布时间对seo的影响
# 抚顺企业网站优化平台
# 关键词排名前转化率低
# 大良营销网站建设机构
# SEO赚钱文案夏天
# 保温杯营销策划推广方案
# 大连seo入门
# 叉车网站推广合作协议
# 这是
# java
# 它将
# 这是因为
# 它会
# 多个
# 而不是
# 多条
# 默认值
# 自定义
# 常见问题
# ai
# 前端
相关栏目:
【
Google疑问12 】
【
Facebook疑问10 】
【
优化推广96088 】
【
技术知识133117 】
【
IDC资讯59369 】
【
网络运营7196 】
【
IT资讯61894 】
相关推荐:
HTML Canvas文本样式定制指南:解决外部字体加载与应用难题
虫虫漫画绿色安全入口_虫虫漫画绿色安全入口安全看漫画
Python实战:高效处理实时数据流中的最小/最大值
Python实时数据流中高效查找最大最小值
海棠阅读登录教程_详细讲解海棠登录操作
火狐浏览器如何刷新修复浏览器 火狐浏览器“重置Firefox”功能详解
花生壳内网映射新方案
使用 .htaccess 正确配置 WordPress 子目录重定向与路径保留
智学网app怎么登录忘记密码_智学网app忘记密码找回与重新登录操作方法
漫蛙漫画官方版直通入口 2025漫蛙漫画免注册访问说明
基于键值条件高效映射 Pandas DataFrame 多列数据
国际经济与贸易就业方向解析
Flexbox布局实践:实现底部页脚与顶部粘性导航条的完美结合
如何通过settings.json个性化您的VS Code体验
百度地图离线地图无法加载如何解决 百度地图离线地图加载优化方法
iphone16系列配置参数介绍
消除网页顶部意外空白线:CSS布局常见问题与解决方案
Excel怎么用XLOOKUP函数实现双向查找_ExcelXLOOKUP替代VLOOKUP+HLOOKUP的高级用法
C++如何实现矩阵乘法_C++二维数组矩阵运算代码示例
Python csv 模块处理非字符串数据:列表写入 CSV 文件的机制解析
学习通网页版课程打不开_课程无法访问时的解决方法
c++如何实现一个简单的RPC框架_c++远程过程调用原理与实践
《原神》月之一版本新增书籍一览
PHP utf8_encode 字符编码转换疑难解析与最佳实践
虫虫漫画排行榜单入口_虫虫漫画编辑推荐入口
抖音小程序怎么开通?小程序开通条件是什么?
PDF如何批量加注释_PDF多文件批注高亮操作教程
iCloud官方网站 iCloud网页版在线登录入口
小红书网页版首页入口 小红书网页版电脑端官方登录链接
《律学法考》查看学习数据方法
《下一站江湖2》心法融合技巧
无人机考证官网 中国民航无人机考证官网登录入口
Go语言反射机制:如何访问被嵌入结构体遮蔽的方法
Word如何将文字快速转成表格 Word文本转换成表格功能使用技巧【效率】
实现二叉树的层序插入:基于树大小的路径导航
4399造梦西游3无敌版_4399游戏入口
《密马》发布账号方法
铁路12306怎么申请退票_铁路12306退票申请操作流程
Win10关闭UAC用户账户控制的方法 Win10降低安全提示等级【技巧】
《荔枝fm》导出文件教程
《淘票票》添加到苹果钱包教程
《虎扑》取消评分记录方法
夸克浏览器资源嗅探怎么用 夸克浏览器网页资源下载技巧【教程】
蛙漫2(台版)正版官网 2025免费网页版分享
Win10如何彻底关闭OneDrive Win10禁用云同步功能【纯净】
iPhone 13 mini如何清理Safari缓存_iPhone 13 mini浏览器缓存清理方法
《百果园》充值余额方法
漫蛙manwa2网页版书签同步链接_漫蛙manwa多设备登录入口
纯CSS实现滚动时动态时间轴线条颜色填充效果
CSS动画如何实现图标旋转并放大_transform rotate scale @keyframes实现
2025-12-08
运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。