- 浏览: 263417 次
- 性别:
- 来自: 南京
-
文章分类
最新评论
-
xuhuan1108:
请问必须都是主键吗?@PrimaryKeyJoinColumn ...
用@SecondaryTable实现多表联合到一个实体 -
renwanly:
共享一下,还是注册服务是王道:http://vboxvmser ...
让VirtualBox的虚拟机器在电脑开机时自动启动 -
liuyuantp:
结果取整。
计算总页数算法 -
jespring:
当数据量很大的时候,在建索引过程中,电脑挂了后,再继续建索引, ...
第28章、Hibernate Search -
meteormatt:
我试了下,怎么会不能用?
Eclipse更新站点
Seam Bean验证快速进阶II:自定义约束
由于百度空间不支持自己在文章中写css代码,所以排版非常简单。优化排版版本请参见:
http://blog.csdn.net/stenlylee/archive/2008/06/24/2583476.aspx
本文为Bean验证系列的第二部分。总体介绍请阅读这篇文章。本文主要介绍了约束定义。
可以通过内置约束(例如@NotNull、@Length等)来进行Bean验证,本文介绍的主要部分为基础验证的扩展。我们非常鼓励开发人员针对具体的业务需求编写自定义约束。
编写自定义约束
由于编写自定义约束是本文的关键部分,所以我们将主要关注于尽可能地简化相关操作。下面让我们开始吧。
正如我们在第一部分中看见的,约束主要由两个部分组成:
1、注释(annotation)
2、实现(implementation)
约束注释的定义
每个约束对应一个注释。你可以把注释当作一个安全的别名和一个描述符。我们可以在声明约束注释的时候添加一个以上的参数,用以实现各种不同的自定义行为。
public class Order { @NotNull @OrderNumber private String number; @Range(min=0) private BigDecimal totalPrice; ... }
我们来看一下@OrderNumber注释的定义:
@Target({METHOD, FIELD}) @Retention(RUNTIME) @ConstraintValidator(OrderNumberValidator.class) public @interface OrderNumber { String message() default "{error.orderNumber}"; String[] groups() default {}; }
约束注释只比一般的注释多了一点东西:
必须使用运行时拦截策略:Bean验证会在运行时检查你的对象
必须使用@ConstraintValidator注释
必须有message属性
必须有groups属性
@ConstraintValidator表示了这个Bean验证类是一个约束注释。它同样也是实现约束注释的惯例(我们随后会详细介绍它)。
message属性(通常赋予一个默认的关键字)用来覆盖默认的验证错误列表。我们会在以后的文章中详细描述这一部分。
groups属性定义了一些列子约束。它实现了部分验证和按照指定顺序验证。我们会在以后的文章中详细描述这一部分。
在这两个必备属性之外, 我们可以根据具体的验证逻辑来定义一些参数。这些参数会被传递给具体的约束实现。例如,一个@Range(范围)注释可能会需要一个最小值属性和一个最大值属性。
@Target({METHOD, FIELD}) @Retention(RUNTIME) @ConstraintValidator(RangeValidator.class) public @interface Range { long max() default Long.MAX_VALUE; long min() default Long.MIN_VALUE; String message() default "{error.range}"; String[] groups() default {}; }
现在,我们能够很快建立一个包含参数的约束了。下面我们需要一些具体的验证逻辑。
约束的实现
约束的实现类与约束的注释接口通过@ConstraintValidator关联。在早先的开发草案中,@ValidatorClass有时用来替代@ConstraintValidator:最终我们改变了这种错误的方式,对不起。约束实现类必须实现一个非常简单的接口Constraint<A extends Annotation>,这里A是一个目标约束注释。
public class OrderNumberValidator implements Constraint { public void initialize(OrderNumber constraintAnnotation) { //no initialization needed } /** * Order number are of the form Nnnn-nnn-nnn when n is a digit * The sum of each nnn numbers must be a multiple of 3 */ public boolean isValid(Object object) { if ( object == null) return true; if ( ! (object instanceof String) ) throw new IllegalArgumentException("@OrderNumber only applies to String"); String orderNumber = (String) object; if ( orderNumber.length() != 12 ) return false; if ( orderNumber.charAt( 0 ) != 'N' || orderNumber.charAt( 4 ) != '-' || orderNumber.charAt( 8 ) != '-' ) return false; try { long result = Integer.parseInt( orderNumber.substring( 1, 4 ) ) + Integer.parseInt( orderNumber.substring( 5, 8 ) ) + Integer.parseInt( orderNumber.substring( 9, 12 ) ); return result % 3 == 0; } catch (NumberFormatException nfe) { return false; } } }
initialize方法通过参数的方式接收约束注释。这个方法一般会执行以下任务:
为isValid方法准备参数
如果需要的话,获得一些扩展资源
正如你所见,这个接口将注意力完全放在了验证逻辑上,将其他所有烦人的部分例如错误显示交给了bean验证提供者。
isValid负责验证具体的值。一些有趣的东西值得我们关注下:
isValid方法必须支持并发调用
当传入的对象类型和预期的不一样,必须抛出错误
null不被认为是无效的:规范文档中推荐将各种验证分离,如果一个值不能为空,则用@NotNull来限制
这些简单的定义让程序员能够自由编写约束进行验证
允许多次使用同种约束
特别需要说明的,在使用groups的时候,你有时可能需要对同一个元素多次应用同一种约束。Bean验证规范特别考虑了这种包含一组约束注释的注释类型。
@Target({METHOD, FIELD}) @Retention(RUNTIME) public @interface Patterns { Pattern[] value(); } @ConstraintValidator(PatternValidator.class) @Target({METHOD, FIELD}) @Retention(RUNTIME) public @interface Pattern { /** regular expression */ String regex(); /** regular expression processing flags */ int flags() default 0; String message() default "{validator.pattern}"; String[] groups() default {}; }
在这个例子中,你可能会需要对同一个属性多次使用这种约束验证。
public class Engine { @Patterns( { @Pattern(regex = "^[A-Z0-9-]+$", message = "must contain alphabetical characters only"), @Pattern(regex = "^....-....-....$", message="must match ....-....-....") } ) private String serialNumber; ...
构建约束
默认情况下,Bean验证使用无参构造器实例化约束验证实现类。然而,规范也提供了一个扩展,该扩展将指向实例化进程的指针提供给其他依赖的管理工具库,例如Web Beans,Guice,Spring,JBoss Seam甚至JBoss Microcontainer。
根据不同管理工具的功能,我们期望在需要的时候验证的实现类能够接受到注入的资源:这个功能的实现完全取决于所依赖的管理工具。
类级约束
一些人可能会比较担心,能否实现跨越多个属性的验证,或者能否实现直接基于许多属性的约束。最典型的莫过于地址验证。地址通常需要复杂的规则来验证:
街道的名字还稍微能够确定,并且肯定能够进行长度限制
不同国家的邮编构成几乎都不一样
城市通常与邮编互相关联,因此能够实现一些错误检查(假设能够通过一种验证服务来完成)
由于这些互相依赖的条件,一个简单的属性级别的验证很难满足这种需求
Bean验证规范提供的解决方案涵盖了这两个方面:
它能够强制要求一组约束执行后,再执行组(groups)和组员次序(group sequences)内规定的另外一组约束。这个主体将在下一篇博客文章中介绍。
它允许定义类级别的约束
类级别的约束是规定不变的约束(注释和实现),它被应用在class上而不是属性上。换一种说法,类级别的约束接受的是实例化的对象,而不是属性值,即传递给isValid方法的参数。
@Address public class Address { @NotNull @Max(50) private String street1; @Max(50) private String street2; @Max(10) @NotNull private String zipCode; @Max(20) @NotNull String city; @NotNull private Country country; ... } @ConstraintValidator(MultiCountryAddressValidator.class) @Target(TYPE) @Retention(RUNTIME) public @interface Address { String message() default "{error.address}"; String[] groups() default {}; } public class MultiCountryAddressValidator implements Constraint { public void initialize(Address constraintAnnotation) { //initialize the zipcode/city/country correlation service } /** * Validate zipcode and city depending on the country */ public boolean isValid(Object object) { if ( ! (object instanceof Address) ) throw new IllegalArgumentException("@Address only applies to Address"); Address address = (Address) object; Country country = address.getCountry(); if ( country.getISO2() == "FR" ) { //check address.getZipCode() structure for France (5 numbers) //check zipcode and city correlation (calling an external service?) return isValid; } else if ( country.getISO2() == "GR" ) { //check address.getZipCode() structure for Greece //no zipcode / city correlation available at the moment return isValid; } ... } }
我们将高级的验证规则写在地址对象的前面,并且通过MultiCountryAddressValidator来实现它。通过处理这个实例化的对象,类级别的验证拥有更大的灵活性,并且能够对相互关联的多个属性进行验证。注意,这里的命令放在了等式的外面(Note that ordering is left out of the equation here),我们会在下一篇文章中回到这个例子。
专家组已经针对各种不同的多属性验证进行了多次讨论:我们认为类级别的约束验证相对其他属性级别的约束验证(包括属性依赖关系验证方式)更加简单和灵活。我们同样欢迎你的任何反馈。
结束语
自定义约束为JSR 303 Bean Validation灵活性表现的核心。编写自定义约束肯定不会被认为是一件困难的事情:
这种验证规则会是你所期望的最严谨验证语法
在代码中小心使用注释名称,将会让你的程序非常易读
如果你有什么想法,请告诉我们。你可以下载完整的规范草案。下一次发表的博客文章将介绍groups、约束子集和验证顺序。
发表评论
-
ERROR [TomcatDeployment] ENC setup failed
2009-11-21 02:16 2057通常这个问题出现在persistence.xml文件有问题的时 ... -
Seam下载文件的问题
2009-08-11 18:24 1466Seam默认下载文件会变成直接在网页中打开内容,主要是因为Re ... -
利用seam-gen来将Seam身份认证管理系统加入到你的项目中
2009-03-20 09:52 1334最近几个月我已经塞了一大堆功能到seam-gen中去了。在我刚 ... -
rich:dataTable中链接传参数不起作用的问题
2009-03-10 17:08 2849经常在一个dataTable里面的放一列,内容是对该条记录的操 ... -
Seam中使用@In @create @Logger需要注意的地方
2009-03-07 17:34 1993以下是我做的一些试验,之所以做这些试验,还是因为我对Seam的 ... -
在JBoss Seam中使用GWT
2009-02-04 18:04 1994原文地址:http://dev.ymeng.net/integ ... -
Seam中基于ACL的权限控制(1)
2009-01-23 01:24 3109Seam框架已经能够解决大 ... -
seam项目实例
2009-01-16 03:42 1323http://www.daying.gov.cn/ ... -
在Jboss Seam中使用PojoCache 和Page Fragment Cache
2009-01-16 03:40 948图片见:http://hi.baidu.com/stenlyl ... -
扩展seam组件
2009-01-16 03:38 1432任何一个框架都必须拥 ... -
seam发送邮件email示例
2009-01-16 03:37 2205以下转自csdn上的一个回答,留着用的时候参考,防止到时找不到 ... -
deleted entity passed to persist
2009-01-16 03:36 5912该错误很可能出现在如下情况: Role和Permission为 ... -
Seam中 EntityHome的remove方法需要加@End声明Conversation结束
2009-01-16 03:36 1204原文:http://seam.group.iteye.com/ ... -
Seam与OpenLDAP的集成(一)
2009-01-16 03:12 1205原文地址:http://shane.bryzak.com/bl ... -
Seam启动流程
2009-01-16 03:08 1208检测包含seam.properties或/META-INF/c ... -
我在seam官网提的问题
2009-01-16 02:51 11181、How to grant permissions with ... -
Hibernate Search, Lucene 与 JBoss Seam
2008-09-28 17:36 940原文地址:http://www.abstractec.c ...
相关推荐
基于万能逼近原理的自适应模糊控制算法在多自由度AUV运动控制中的应用与抗干扰补偿Simulink仿真研究,自适应模糊控制算法的万能逼近原理与多自由度AUV运动控制的抗干扰补偿技术——基于Simulink的仿真研究,万能逼近原理自适应模糊控制算法的多自由度AUV运动控制抗干扰补偿simulink仿真 ,核心关键词:万能逼近原理; 自适应模糊控制算法; 多自由度AUV运动控制; 抗干扰补偿; Simulink仿真。,基于万能逼近的模糊控制算法多自由度AUV抗干扰补偿Simulink仿真
deepseek最新资讯、配置方法、使用技巧,持续更新中
deepseek最新资讯、配置方法、使用技巧,持续更新中
结合扩展卡尔曼滤波与滑模观测器的策略:优化电角度估计,反电势波形逼近完美正弦波,结合扩展卡尔曼滤波与滑模观测器的反电势波形优化:正弦波形展现近乎完美精度,电角度估算与实际应用差异微小,扩展卡尔曼滤波与滑模观测器的结合,反电势波形近乎完美的正弦波形,观测器估算转子电角度与实际电角度相差0.3弧度左右,转速跟随效果较好。 ,核心关键词:扩展卡尔曼滤波; 滑模观测器; 反电势波形; 转子电角度估算; 转速跟随效果。,卡尔曼滑模观测器:优化正弦波转子角度与转速估算
毕业设计_基于springboot+vue的**学生公寓管理系统**【源码+sql+可运行】【**50217**】.zip 全部代码均可运行,亲测可用,尽我所能,为你服务; 1.代码压缩包内容 代码:springboo后端代码+vue前端页面代码; 脚本:数据库SQL脚本 效果图:运行结果请看资源详情效果图 2.环境准备: - JDK1.8+ - maven3.6+ - nodejs14+ - mysql5.6+ - redis 3.技术栈 - 后台:springboot+mybatisPlus+Shiro - 前台:vue+iview+Vuex+Axios - 开发工具: idea、navicate 4.功能列表 - 系统设置:用户管理、角色管理、资源管理、系统日志 - **业务管理:业务管理:公寓信息、房间信息、入住记录、学生信息** 3.运行步骤: 步骤一:修改数据库连接信息(ip、port修改) 步骤二:找到启动类xxxApplication启动 4.若不会,可私信博主!!!
1、文件内容:xorg-x11-server-source-1.20.4-29.el7_9.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/xorg-x11-server-source-1.20.4-29.el7_9.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、更多资源/技术支持:公众号禅静编程坊
1、文件内容:yum-plugin-ps-1.1.31-54.el7_8.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/yum-plugin-ps-1.1.31-54.el7_8.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、更多资源/技术支持:公众号禅静编程坊
基于模型预测控制(MPC)的无人船与无人车编队一致性协同控制研究(附原文献),基于模型预测控制(MPC)的无人船与无人车编队一致性协同控制研究(附原文献),无人船编队 无人车编队 MPC 模型预测控制 多智能体协同控制 一致性 MATLAB 无人车 USV 带原文献 ,无人船编队; 无人车编队; MPC 模型预测控制; 多智能体协同控制; 一致性; MATLAB; USV; 原文献,无人系统协同控制:MPC模型预测控制下的多智能体编队与一致性研究(原文献支撑)
4套中级通信工程师综合真题及答案(2019,2020,2021,2023),适用于需要考中级通信工程师的人群
deepseek最新资讯,配置方法,使用技巧,持续更新中
基于matlab的锁相环PLL相位噪声拟合仿真代码集合:多个版本建模与仿真,高质量的锁相环PLL仿真代码集合:Matlab与Simulink建模研究,[1]锁相环 PLL 几个版本的matlab相位噪声拟合仿真代码,质量杠杠的,都是好东西 [2]锁相环matlab建模稳定性仿真,好几个版本 [3]锁相环2.4G小数分频 simulink建模仿真 ,PLL; Matlab相位噪声拟合仿真; Matlab建模稳定性仿真; 锁相环2.4G小数分频Simulink建模仿真,MATLAB仿真系列:锁相环PLL及分频器建模仿真
exceptionLogs.zip
基于光伏微网的经济性与并网负荷波动率双目标优化调度策略:蓄电池与V2G协同管理策略仿真研究,MATLAB下光储充微网结合电动汽车V2G的多目标协同调度策略研究:经济性与并网负荷波动性的对比分析,MATLAB代码:考虑V2G的光储充一体化微网多目标优化调度策略 关键词:光储充微网 电电汽车V2G 多目标优化 蓄电池优化 调度 参考文档:《光伏微网下考虑V2G补偿蓄电池容量的双目标优化调度策略》,已经投稿EI会议,中文说明文档可联系我咨询 仿真平台:MATLAB 平台 优势:代码注释详实,适合参考学习,相关成果已经采用,程序非常精品,请仔细辨识 主要内容:过建立光伏微网中以经济性和并网负荷波动率为双目标的蓄电池和V2G的协同调度模型。 采用粒子群算法,对电网、微网调度中心和电动汽车用户三方在无、无序、转移和调度V2G电动汽车负荷四种运行模式下的经济和安全影响进行对比。 最后,根据算例分析,求解四种模式下两级负荷曲线及经济收益表。 对比分析得出,引入V2G可以替代部分容量的蓄电池,使光伏微网在负荷峰谷平抑、三方经济和安全等方面进一步优化。 求解采用的是PSO算法(粒子群算法),求解效果极
javascript 动态网页设计期末大作业(自己手写的,高分期末作业),含有代码注释,新手也可看懂,个人手打98分项目,导师非常认可的高分项目,毕业设计、期末大作业和课程设计高分必看,下载下来,简单部署,就可以使用。该项目可以直接作为毕设、期末大作业使用,代码都在里面,系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值,项目都经过严格调试,确保可以运行! javascript 动态网页设计期末大作业(自己手写的,高分期末作业)javascript 动态网页设计期末大作业(自己手写的,高分期末作业)javascript 动态网页设计期末大作业(自己手写的,高分期末作业)javascript 动态网页设计期末大作业(自己手写的,高分期末作业)javascript 动态网页设计期末大作业(自己手写的,高分期末作业)javascript 动态网页设计期末大作业(自己手写的,高分期末作业)javascript 动态网页设计期末大作业(自己手写的,高分期末作业)javascript 动态网页设计期末大作业(自己手写的,高分期末作业)javascript 动态网页设计期
混合智能体系统编队控制:分布式优化与15异构混合阶的挑战,异构混合阶智能体系统编队控制的分布式优化策略研究,15异构混合阶多智能体系统编队控制的分布式优化(无参考文献) ,核心关键词:15异构混合阶; 多智能体系统; 编队控制; 分布式优化; 无参考文献。,15混合阶多智能体系统编队分布式优化控制
javascript 动态网页设计期末大作业(自己手写的,很适合期末作业),含有代码注释,新手也可看懂,个人手打98分项目,导师非常认可的高分项目,毕业设计、期末大作业和课程设计高分必看,下载下来,简单部署,就可以使用。该项目可以直接作为毕设、期末大作业使用,代码都在里面,系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值,项目都经过严格调试,确保可以运行! javascript 动态网页设计期末大作业(自己手写的,很适合期末作业)javascript 动态网页设计期末大作业(自己手写的,很适合期末作业)javascript 动态网页设计期末大作业(自己手写的,很适合期末作业)javascript 动态网页设计期末大作业(自己手写的,很适合期末作业)javascript 动态网页设计期末大作业(自己手写的,很适合期末作业)javascript 动态网页设计期末大作业(自己手写的,很适合期末作业)javascript 动态网页设计期末大作业(自己手写的,很适合期末作业)javascript 动态网页设计期末大作业(自己手写的,很适合期末作业)javascrip
X光安检OPIXray数据集已经转换为VOC格式,可直接转换为为YOLO
DataX--Web:图形化界面简化大数据任务管理_datax-web
# 踏入C语言的奇妙编程世界 在编程的广阔宇宙中,C语言宛如一颗璀璨恒星,以其独特魅力与强大功能,始终占据着不可替代的地位。无论你是编程小白,还是有一定基础想进一步提升的开发者,C语言都值得深入探索。 C语言的高效性与可移植性令人瞩目。它能直接操控硬件,执行速度快,是系统软件、嵌入式开发的首选。同时,代码可在不同操作系统和硬件平台间轻松移植,极大节省开发成本。 学习C语言,能让你深入理解计算机底层原理,培养逻辑思维和问题解决能力。掌握C语言后,再学习其他编程语言也会事半功倍。 现在,让我们一起开启C语言学习之旅。这里有丰富教程、实用案例、详细代码解析,助你逐步掌握C语言核心知识和编程技巧。别再犹豫,加入我们,在C语言的海洋中尽情遨游,挖掘无限可能,为未来的编程之路打下坚实基础!