推荐序一 ——REST开发的理想与现实
REST是一种分布式应用的架构风格,也是一种大流量分布式应用的设计方法论。REST是由(构成了Web基础架构的)HTTP、URI等规范的主要设计者Roy Fileding博士在其2000年的博士论文(中文版名为《架构风格与基于网络应用软件的架构设计》)中提出的。到目前为止,关于REST最系统、最全面的论述,仍然是Fielding的博士论文。
REST就是Web(World Wide Web,简称Web或者WWW)本身的架构风格,是设计、开发Web相关规范、Web应用、Web服务的指导原则。不符合REST风格要求的架构和技术,很难在Web这个生态系统中得到繁荣发展。在我看来,Roy Fielding博士就是15年以来对于分布式应用架构设计理论贡献最大的人。Fielding在HTTP规范的设计过程中,并没有采用当时大行其道的DO(Distributed Object,分布式对象)风格,而是自出机杼、另辟蹊径,提出了一整套新的设计方法论。Fielding的开创性工作,极大地推动了分布式应用设计理论的发展。
有趣的是,其实基于SOAP/WSDL的“大Web Service”(以下简称Web Service),几乎是与REST同时发展起来的。虽然在Web Service中也使用了对象,但是Web Service其实是RPC风格的,而不是DO风格的。Web Service在最初几年发展很快,很大原因是它解决了DO风格难以解决的异构系统(不同的硬件系统、不同操作系统、不同的编程语言,等等)之间互操作性的问题。
然而遗憾的是,设计Web Service协议栈的核心人员,几乎都是来自于企业应用阵营的,尤其是来自于IBM和微软两家公司的人。这些企业应用的专家们没有充分认识到Web基础架构的巨大优点,甚至可以说并没有理解HTTP协议究竟是用来做什么的、为何要如此设计。在Web Service协议栈的设计之中,仍然有深深的企业应用痕迹。Web Service虽然宣称能够很好地支持互操作,然而因为协议栈的复杂性很高,在实战中互操作性并不好(例如升级过程困难而且复杂)。此外,Web Service仅仅将HTTP协议当做一种传输协议来使用,还依赖XML这种冗余度很高的文本格式,这导致Web Service应用性能低下。很多开发团队宁可使用Hessian等轻量级的RPC协议,也不愿意使用Web Service。在面向互联网的大流量Web应用(包括Web服务在内)这种运行环境中,Web Service在复杂性、互操作性、性能、可伸缩性等方面的短板更加突出。因此,设计今日面向互联网的API,已经很少有人会考虑Web Service。这使得Web Service的使用被局限在企业应用运行环境之中,其名称中的“Web”更像是一个笑话(除了都使用HTTP协议,基本上与Web没什么关系)。假如在2000年,设计Web Service规范的专家们,能够认真读一下Fielding的博士论文,或者找HTTP、URI等Web基础架构规范的核心设计人员深入交流一下,Web Service很可能就不是现在这个样子了。不过,历史是无法假设的。
在Java世界中,与大Web Service相对应的规范是JAX-WS。在大Web Service已经成为明日黄花之后,Java世界急需一套新的规范来取代JAX-WS。这套新的规范就是JAX-RS:Java世界开发RESTful Web Service(与RESTful API含义相同,可混用)的规范。虽然起步很晚,毕竟走上了正确的道路。
从Java EE 6开始,JAX-RS在Java EE版图中,作为最重要的组成部分之一,逐步取代了JAX-WS的地位。在所有Java EE相关规范中,JAX-RS是优点很突出的一个。例如,完全基于POJO、很容易做单元测试、将HTTP作为一种应用协议而不是可替代的传输协议(因此提高了性能)、优秀的IDE集成,等等。可以说,在大多数场合,JAX-RS完全可以取代JAX-WS,作为Java Web Service开发的主要技术。JAX-RS同样也可以完全取代Hessian等基于HTTP协议的RPC风格远程调用协议。毕竟HTTP本身就是一种REST风格的应用协议,以REST风格来使用HTTP,才是最高效的使用方式。
Jersey、CXF等支持JAX-RS规范的REST开发框架还支持输出WADL。WADL支持客户端代码自动生成,还可以将WADL导入到SoapUI等测试工具中,然后做自动化集成测试。从开发Java企业应用、取代JAX-WS的角度来看,JAX-RS已经做得非常棒了。
尽管如此,不可不提的是,JAX-RS这套规范,仍然存在着很多遗憾。需要特别指出的是,JAX-RS规范并不等于REST架构风格本身,REST的内涵要比JAX-RS广泛得多。学会了使用JAX-RS了,并不等于就完全理解了REST,开发者仍然需要下工夫认真学习一下本源的REST究竟是什么。
例如,JAX-RS规范对于应该如何定义一个资源,以及应该如何使用HTTP作为一个统一接口来操作资源,显然缺乏必要的指导。有很多开发者只是简单地将以前JAX-WS中的一个endpoint接口转换成一个资源接口。接口的方法太多,导致映射到的HTTP方法不够用,这也难不倒他们,在URI路径中加一些字符串就能够解决(例如,三个接口方法都映射到POST,但是其PATH不同)。这样的开发方式非常常见,虽然开发者使用了JAX-RS规范,但是开发方式完全是RPC风格的,可以说与REST风格没有任何关系。
此外,JAX-RS规范目前尚不支持HATEOAS(将超文本作为应用状态的引擎,REST风格的核心特征之一),从著名的Richardson成熟度模型(由《RESTful Web APIs》的作者Richardson提出)来衡量,基于JAX-RS规范实现的RESTful API仅仅能够达到成熟度模型的第二级,即支持资源抽象、统一接口的“CRUD式Web服务”。
可以这样说,JAX-RS规范与真正的REST风格,覆盖的范围其实是不同的。JAX-RS覆盖的是简单基于HTTP协议(没有使用SOAP/WSDL)的各种远程调用需求,很多需求对于可伸缩性、松耦合的要求并不高,仅仅是希望使用HTTP本身来取代大Web Service作为一种轻量级、容易测试的远程调用协议。REST架构风格的严格要求,在这些场合并不是非常重要。慵懒是人类的天性,大多数开发者写代码只是为了解决手头的问题,JAX-WS并不好用,JAX-RS解救了他们。
如果按照Roy Fielding博士的严格要求(REST APIs must be hyper-text driven),那么包括JAX-RS规范在内都不能算是真正的RESTful。然而,从实战角度,我认为革命不分先后,只要能够达到Richardson成熟度模型第一级,即有清晰的资源抽象,就可以认为是RESTful API了。如果连第一级都达不到,所设计的架构根本就不是面向资源的,那八成还是RPC风格的,就没有必要非要往RESTful API阵营里面挤了。从来没有人说过RPC就是万恶的,RPC在企业应用的大多数场合其实都非常有效,只是不适合面向互联网的大流量Web应用而已。
因此,能够完美支持HATEOAS,攀登到成熟度模型第三级,是一种理想情况(当然也是值得追求的)。而通过部分拥抱REST风格的要求,来更好地解决手头的问题,是更多开发者所面对的现实情况。JAX-RS反映的正是这种现实情况,从实战的角度,它是一套非常有用也很好用的规范。
韩陆兄的新著《Java RESTful Web Service实战》是JAX-RS规范方面的专著,也是国内第一本REST开发的原创著作。这本书的实战性非常强,全面介绍了JAX-RS 2.0的方方面面,可以作为一线Java分布式应用开发者的案头必备书。如同我在前面所指出的,JAX-RS规范并不等于REST架构风格本身,它们有着不同的覆盖范围。在本书中,作者也介绍了很多设计RESTful API的最佳实践,这些内容假如读者不理解REST,甚至在亲自阅读了JAX-RS规范之后也未必能够总结出来。读者在阅读本书的过程中,不应该仅仅满足于掌握了JAX-RS开发的基本方法、解决了手头的问题、用其完全取代JAX-WS,更重要的是,读者还应该就REST架构风格本身做更多的学习。幸运的是,除了本书之外,目前REST设计和开发方面的图书资料已经非常多了。
本书的内容非常严谨,有非常好的系统性,对于设计开发大流量Web服务会面临的各种问题都有涉及。特别是在自动化测试方面着墨颇多,在我看来是本书的一大亮点。RESTful API的自动化测试非常重要,需要在设计之初就充分考虑到。本书是一本难得的原创佳作,值得所有Java分布式应用的开发者购买。
理想富丽丰满,现实贫瘠骨感,追求理想和注重解决现实问题其实并不矛盾。JAX-RS规范的发展,反映出了Java社区在更好地开发RESTful Web Service方面的求索。尽管存在争议,在我看来,规范化是推动RESTful Web Service取得更大发展的必由之路。目前对于优秀的RESTful API有哪些判断标准,Web开发者社区已经达成了高度共识,也积累了大量非常有价值的成果。JAX-RS规范的发展,离不开Web开发者社区的这些成果。在未来的JAX-RS 3.0规范中,我们将会看到更多令人兴奋的成果被规范化。JAX-RS 2.0已经做得不错了,但是在RESTful Web Service规范化的道路上,其实才刚刚起步,任重而道远。
李锟 于上海