BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

Emmanuel Bernard谈Bean验证规范

| 作者 Charles Humble 关注 906 他的粉丝 ,译者 王丽娟 关注 0 他的粉丝 发布于 2008年7月16日. 估计阅读时间: 16 分钟 | QCon上海2018 关注大数据平台技术选型、搭建、系统迁移和优化的经验。

接着之前一篇关于Bean验证框架草案的文章,InfoQ有幸采访到了Emmanuel Bernard,向其了解了专家组正在寻求的建议和社区参与的更多相关信息。

InfoQ:我之前很期望规范能支持某种XML模型和Annotation,但规范似乎没有。这些内容你是不是已经移除了呢?

Emmanuel Bernard (EB):规范将支持XML模型。不过我们最初是想先解决功能集和元模型,然后再仔细检查XML描述符的处理过程。Annotation可用做JSR 303 Bean验证实现中的内部模型。一旦我们正确定义了Annotation模型,我们就无需再使用XML了,这仅仅是另一种语言。

InfoQ:你们打算支持错误消息的层次吗?——这样,我能用标准的方式显示一个通用的错误消息,如果我愿意,我可以用页面/屏幕特定的错误消息覆盖那个通用的错误消息。

EB:我不是很确定我理解了你的问题,但是让我从两个角度来试着回答一下
a)Bean验证规范能让你通过基于ResourceBundle本地化的标准文件系统来外部化和国际化约束错误消息。约束可以声明一个关键字,而不是使用“硬编码”的消息。

@Length(max = 50, message="{constraint.name.tooLong}")
String name;

## French resourceBundle constraint.name.tooLong =
Le nom ne peut dépasser {max} caractères

为了超越这一模式、提供一种与应用或展示框架(比如Web框架)的自然集成,该消息解决策略完全是可插拔的。

让我们举一个例子:Web Beans促进了上下文相关组件(比如事件、页面、请求、会话、业务流程)的思想。Web Beans可以利用Bean验证,并插入其上下文知道的消息解决策略:包含上下文相关表达式的错误消息接着会被处理。

另一个例子是,Wicket的资源包解决方案是分层定义的。它首先尝试在面板资源文件中查找关键字,然后是页面资源文件,最后才是应用资源文件。遵照这一模式,Wicket能提供它自己的消息解决实现。

在这两种情况下,对提供合适的错误消息来说,上下文相关的信息至关重要。Bean验证调用者处于辨别该上下文更好的位置上:通过提供一个自定义的消息解决实现,在仍然能将验证工作委派给Bean验证的同时,Bean验证调用者还能给使用者提供一个自然、同源的体验。

b)更为理性地说,我想知道你为什么需要改变某个特定页面的约束消息呢?一条约束消息需要在特定上下文中“自定义”通常是因为,看似是一个约束的内容,实际上是两个适用于不同上下文的不同约束。Bean验证规范提供了描述上下文相关约束的机制。每个约束属于一或多个组。验证对象的时候,会列出一个组列表,以供对使用验证的上下文进行选择。我在一篇博文中描述了一些适用于组的用例。

InfoQ:国际化和验证有一个共同的问题,就是不同地区之间验证规则可能会有所不同。比如字母数字的测试可能会有不同。这该如何处理呢?

EB:我通常看到的是,约束规则对属性值的依赖要比对实际地区的依赖要多。为了举一个地址的规范例子,邮编或电话号码约束会根据该地址所属的国家不同而不同。

一些约束不会有变化(非空、数据库中的最大长度),但有一些会因国家而不同。规范现在通过提供类级别的约束处理了这一问题。类级别的约束能获取Bean实例,而不是它的某一属性,还能应用一些基于若干属性的约束。电话号码验证逻辑可以适用于法国和美国的不同规则,它甚至可以为加拿大的电话号码调用外部服务,加拿大的电话号码基于已存在的数据库,而不是格式化的规则。

这是一个有趣的问题,人们可以对应该有什么解决办法而有不同的尝试。类级别的方法提供了最大的灵活性,并保持了规范的简单性。争论仍然很激烈:如果你有什么意见,可以到http://forum.hibernate.org/viewforum.php?f=26发言:)

InfoQ:我们能使用表达式语言(Expression Language)巧妙地处理错误消息吗?或者说我们有消息的插入点吗(在{x}和{y}中间插入一个数字)?

EB:是的,缺省的消息处理策略允许约束参数的注入。

@Length(max = 50, message="{constraint.name.tooLong}")
String name;
constraint.name.tooLong = Names must not be longer than {max} characters

上面这段内容会得到消息:名称不得超过50个字符。

但这显然是专家组正在寻求反馈和建议的领域。在Bean验证反馈论坛上已经开始了一些讨论,以便提供额外的上下文相关信息。

而且正如我先前描述的那样,自定义消息解决策略可以提供给Bean验证提供商:这是提供与现有Web和应用框架自然集成的关键。我认为应用和Web框架在它们处理方式上的信息要比Bean验证框架更多,所以它们能提供一个更好的变量替换和表达式语言解决办法。

InfoQ:你打算支持错误消息中的超链接吗?如果有的话,本地化问题该如何处理(比如链接的位置在不同的地区可能会不同)?

EB你所描述的问题对展示框架的依赖性很强。展示框架提供的自定义消息解决策略能完美地处理这种情况,因为演示框架有所有的上下文相关信息(URL根路径、传递的参数等)。

InfoQ:层之间的多语言情景该如何处理?比如说,如果后端系统用一种语言(假定是英语)生成了错误消息,但我需要用另一种语言显示给用户,如粤语。

EB:这是一个非常有趣的问题,可惜我不知道所有的解答,因为它涉及整个Java EE平台,而不仅仅是Bean验证。
如果期望用粤语读取,后端系统就不应该用英语生成错误消息。但规范还没有描述这个问题,专家组期望能提供自定义地区的能力,用于特定的验证调用(可能是通过基于传递模型的线程)。应用框架将负责把地区从客户端传到服务器端。

正如你看到的,集成应用框架(调用者)和Bean验证将会是提供极好的用户体验的关键。不幸的是(或许也是幸运的),这个JSR侧重于约束声明和验证。但是专家组得意识到大局,我们尽量提供必要的扩展和集成点,使使用者能适当地集成。

InfoQ:我希望理想的情况是能用同一个框架处理我所有的验证(假定从JavaScript开始,在应用层,针对数据库)。目前规范离这一目标有多近呢?

EB跨越这些异构层共享相同的约束定义,我认为这一能力才是至关重要的。如果相同的验证框架能被重用,就更好了。

Bean验证是层不可知的,上至展示层、下到DAO层,所有这些Java层都可以简单地将约束验证委派给Bean验证运行时。让我们举几个例子:

  • 每次实体被添加或更新到数据库时,Java持久层可以调用Bean验证
  • 业务构件可以在应用核心业务逻辑之前调用一组数据的Bean验证
  • 展示层可以调用验证逻辑对表单提供的数据进行验证,然后再将该数据传递给域模型
  • 该上下文中的Bean验证是验证运行时引擎,由架构中的各部分进行调用。由于约束被放置在域模型类中、由各个层共享,所以可全面地应用同样的约束。

对Java范围之外的层来说,它变得更加复杂和有趣。数据库就是一个很好的例子。一些约束在数据库Schema中非常合理(非空、长度等等)。Bean验证规范通过元数据请求API暴露一些约束的基本元数据信息。Java持久化能钩到这个API上,提取有用的信息,并将一些约束应用于数据库Schema。

在展示端,特别是在Web应用中,一些约束能被JavaScript代码使用。这减少了到服务器的数据传输次数,通过及早的错误反馈提供了更好的用户体验。在这种情况下有两个方法是可行的。展示Widget(比如JSF组件)能从Bean验证请求API中提取约束元数据,并在JavaScript中使用相同的逻辑。当然不是所有的约束都能用这种模型来表述。尽管它们中的一些将用于客户端。该方法的漂亮之处是客户端和服务器端都能透明地保持一致性,就像它们都能共享来自域模型的约束声明一样。尽管我们不会重用实际的约束实现,但是元数据API提供一些方法来提取约束定义并重用它。第二种方法是使用类似 GWK的方法:Java代码转化为JavaScript:相同的实现逻辑接着会在客户端和服务器端之间共享。

InfoQ:好——那么假设我在Web应用中有一个电话号码属性。该属性是必需的,最大长度是40个字符,而且只接受字母数字。我想在Web端使用JavaScript检查属性的长度。在数据库端,我也定义一个CHAR40字段。如果我想从Web层查找约束验证,我该如何去做?又能获得什么?你了解JPA 2中同样的工作方式吗?

EB你所描述的内容实质上引出了那些超出Java范围的约束。为了使这种情况发生,连接Java世界和Web/JavaScript工作的框架需要:

  • 知道Web表单输入和域模型属性之间的联系
  • 获取到约束描述

第一点是链接框架的任务。通过检查表达式语言(比如在JSF中)这一点就能实现,它能实现是因为这个框架使用“Java”(比如在Wicket中)。

第二点出现是因为链接框架可以从属性中查询Bean验证的元数据API,并接受约束的列表。每个约束(不只实现了验证逻辑)描述了它如何能投映到一组预定义的静态约束范围内。这是什么意思呢?它用冗长的方式表明每一个约束描述是否:

  • 执行非空性、可空性。
  • 执行长度约束。
  • 执行最大值。

等等这些。这将要求展示框架中的一些工作包含并使用Bean验证API,但它还是会给开发人员带来很多的价值。

与Java Persistence进行集成,和生成数据库Schema的方式大部分都将是相同的:仅仅用“列”替换“表单输入”就可以了。

InfoQ:规范受Hibernate验证框架的影响比较大,但是组的概念似乎不是。你能不能告诉我们这个主意是从哪里来的?你是怎么看着它被利用起来的?

EB:规范向Hibernate验证框架借鉴了很多,但也抓住了许多不同验证框架的思想。因此,减少规范中错误的最好方式就是基于现有的工作特性:事实上,规范中的大部分功能要么已经通过实现从头开始的概念进行了验证,要么已经通过对Hibernate验证框架的分支进行了验证,从而保证了它们的成功。

我不知道究竟在何时何地开始了组功能,所以如果我归功错的话,请原谅。我知道Rifle很久以前就有类似的功能了,Hibernate验证框架的用户也要求这一功能。关于组和约束之间的依赖,一般来说比较难的事情是对它们的描述很快就会变得非常非常冗长和复杂。规范试图在灵活性和简单性之间找到平衡。我们在反馈论坛中已经尝试开始一些比较有趣的讨论,并改进它。

在下面几中情况下组会非常重要:

  • 定义约束的一个子集,以根据用例对其分组(用户是有效的,而且用户在一次点击中提供了足够的信息)
  • 验证数据,因为数据是由用户提供的:并非所有的数据都在同一时间内提供。某一特定的对象可能只有部分可验证
  • s一些约束应该在另外一些之后再验证,而且只有前面的验证通过才能进行验证。这可能是因为时间或CPU的代价比较昂贵,或者是因为它们期望数据处于“合适的”状态。

组为这些用例提供了一个声明性的解决方案。我们期望Java Persistence、JSF、Web Beans或任何应用框架都能提供声明性方式去请求组特定的验证。

InfoQ:你如何处理有可能与其他专家组重叠的地方?比如说在JPA2、Web Beans等领域。

EB:严格来说,JSR 303和你提到的规范没有重叠,但有一定的集成机会。尽管集成工作还没有正式开始,但是许多303专家组的成员同时也是JPA 2、JSF 2和Web Beans专家组的成员。我个人是JPA 2专家组的成员,已经对Java Persistence集成思索了一段时间。随着早期的草案发布,其他专家组可以评论并提供反馈,使集成成真。

InfoQ:花多长时间能让原型实现可用呢?

EB:实际上社区超越了我们。你可以找到一些已有的实现。我知道的有http://code.google.com/p/agimatec-validation/.
尽管不兼容(尤其是API方法),Hibernate验证框架还是实现了规范基于的大部分概念,并全面探索了我们刚刚讨论的集成模型:

  • 它集成了Hibernate Core,以同步数据库Schema
  • 它通过标记与JBoss Seam和JSF进行了集成。在将表单属性传递到应用流程的剩余部分之前,标记触发了对表单属性的Hibernate验证的调用
  • 一些UI Widget重用了Hibernate验证框架的约束,并通过JavaScript调用将其应用到客户端

InfoQ:你们要从Java社区得到什么呢?

EB:我们非常盼望获得规范相关的反馈:

  • 它如何能更好得满足应用开发人员的需要(易于使用、用例)
  • 它如何能更好地满足框架开发人员的需要(集成点、重用性)
  • 它如何进行改进

我们已经放弃了一个基于电子邮件的信息反馈系统,开放了一个公开论坛 ,人们可以在那里互动、提问、提出不同的解决方案。这是修改和提高规范的完美时机。迄今为止,反馈都非常好并且很有趣,所以我们将继续进行:)

查看英文原文Interview: Emmanuel Bernard on the Bean Validation specification

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我
社区评论

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT