JAVA 削足适履适应 RESTful 设计

  • Mark Little
  • 李树贤

2013 年 1 月 8 日

话题:REST语言 & 开发架构

没有人可以否认这些年来 Java 在软件开发领域的积极影响。或者说,对众多的开发者和应用程序而言,Java 和 JVM 仍然是占统治地位的通用解决方案。无论是 CORBA、SOA、REST 还是 Web 服务,Java 都能够支持。对于无处不在的 Java 和 REST,二者结合的标准方法的出现(即已经在 EE6 中介绍的 JAX-RS)只是时间问题。目前已经有很多JAX-RS 的实现,包括 Jersey(参考实现)和 RESTeasy,其中 RESTeasy 已经有广泛的应用。

过去几年,虽然对 JAX-RS 有一些争论,特别是围绕它是否支持 RESTful 风格的设计。其中的一些问题,已经被JAX-RS 2.0技术委员会考虑,但是在最近的JavaOne 2012大会上,仍然有一些关于标准的提问。11 月早些时候,Zapthink 的一篇论文也加入了这一论战,再次质疑 Java 甚至 JAX-RS 是否适合于构建 RESTful 应用程序。

Java Community Process(JCP)的不断努力,已增强了 Java 生态系统的能力,以应对范围广泛的新问题和新情况。他们不断对 Java 投入工作,为满足未来几年的需求。但话又说回来,也许不能。Java EE 的重量级的模型-视图-控制器(MVC)架构,或者 Java 简单的面向对象的环境,可能无法支持其它架构方法。

当然,也有些与 Java 无关的蓬勃发展的 JVM 社区,比如 JRuby、Clojure、Scala 和 JavaScript,你不需要为了使用 JavaEE 内部的很多能力(比如事务和安全等)而去学习 Java EE。这些语言本身有一些构建 RESTful 服务的方法。然而,Zapthink 认为, Java 对 JAX-RS 规范的支持特别差劲。

不幸的是,JAX-RS 是一个削足适履的典型例子。它为 Java 增加了一些 RESTful 的功能,但是,却在每一步中又屏蔽了 RESTful 架构风格。例如:HATEOAS约束。JAX-RS 1.1 一点儿都不支持超媒体。这从本质上说,这意味着我们必须利用 Java 的核心能力模拟实现 HATEOAS 特性。为了使 JAX-RS 完全支持 RESTful,我们必须设计满足所有 REST 体系结构约束的应用程序,以补偿那些在开发期间未得到支持的特性。JAX-RS 1.1 为 REST 架构约束提供了丰富的支持,但却丢弃了 HATEOAS。

缺少对超媒体的支持是 JAX-RS 技术委员会试图在最新的版本中解决的问题之一。但是,它远远不能满足该文所关注的:JAX-RS 严重依赖 Java 注解,但是没有注解来阐述超链接,这导致产生了一些临时的方法,可它们却应该是标准的一部分。

文章还指出,一些其他领域,即便新版本标准中也未提及,尽管它们是否应该属于 JAX-RS 或其他标准尚无定论。

同样重要的是,只要有可能,就要将自定义的媒体类型标准化。而且用户还必须选择要使用标准媒体类型及自定义媒体类型。此外,服务可发现性的设计原则以及基于 REST HATEOAS 设计约束,要求在适当的地方进行超媒体控制。可发现性使该协议变的自描述。

最后一点是强加于 JAX-RS 的一个重要约束。ZapThink 认为,它妨碍了 JAX-RS 和 Java 对 RESTful 服务的适应。正如Arun Gupta在讨论 JAX-RS 2.0 的早期草案时所解释的,有两种类型的超媒体链接。

RESTful 的主要原则的之一是链接资源。其中之一是结构性链接,它用来避免发送完整的资源的表述和避免启用延迟加载。客户可以根据这一类型的链接来检索他们所需要的“碎片”。过渡性链接,用来更新资源状态,通常是用一个“rel”属性标识。结构性链接通常在实体内,过渡性连接可能在链接的头部或者实体内。

然而,尽管 JAX-RS2.0 只支持过渡链接的事实,ZapThink 认为,二者对 RESTful 服务都不是绝对必须的。

如果我们简单地定义一个 Java 对象,并把它转换成超媒体,就会得到一个链接,那么该链接则描述了所有方法相关的对象实例,产生巨大的、复杂的表述。相反,JAX-RS 鼓励过渡链接,使得客户端能逐步得到相关潜在的综合信息。但是,如果起先我们没有被 Java 对象的结构所限制,我们就永远不会为过渡链接和结构链接操心。相反,我们需要设计超媒体应用程序使之支持可发现性。换句话说,一个重要的 Java 模式成了超媒体反模式。

除了上述事实,在构建 RESTful 服务方面,JAX-RS2.0 可能仍然存在不足。作者的结论是,你需要记住的是,REST 并不是一种实现,而是一种架构方法。

在开发 JAX-RS 并考虑 REST 时,人们常常感到困惑。JAX-RS 不是为 REST 设计的;否则, JAX-RS 应该能很好的支持 REST 风格的设计。此外,使用 JAX-RS API 并不会产生完全 RESTful 的服务,除非事先已完成合适的 REST 风格设计。该设计必须确保你已经满足所有 RESTful 架构约束。

当然,也有人此前讨论过这可能 REST 或者SOA有关。但有,是否存在一些与 JAX-RS 或用 Java 构建 RESTful 服务相关的根本问题,如 Zapthink 的文章所述?文章的其中一个评论者问到:

非常严肃的说,当用 RESTful 方法构建系统时,你建议用什么语言替代 Java?我知道,Java 正在变得“老迈”,但我坚信强类型化和 Java 体现的其他编程实践等好处。你认为 Scala(下下一代 Java)会更合适吗?如果不是 Scala,那又是什么?

作者回应:

我不会简单地支持任何一种语言,因为我确信,任何编程语言都是有价值的,只要它为实现 REST 兼容的架构提供足够的支持。当然,架构对语言的选择也会产生一定影响。但更重要的是,专注于应用程序的设计,使之符合 REST 设计约束。

仍然留下一个问题:特别是与其他语言相比,Java 是削足适履以适应 Restful 设计了吗?

查看英文原文Shoehorning Java into RESTful Design


感谢马国耀对本文的审校。

给 InfoQ 中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ)或者腾讯微博(@InfoQ)关注我们,并与我们的编辑和其他读者朋友交流。

REST语言 & 开发架构