RESTful Web services: The basics
Alex Rodriguez
Published on November 06, 2008/Updated: February 09, 2015
From IBM:https://www.ibm.com/developerworks/library/ws-restful/
REST defines a set of architectural principles by which you can design Web services that focus on a systems resources, including how resource states are addressed and transferred over HTTP by a wide range of clients written in different languages. If measured by the number of Web services that use it, REST has emerged in the last few years alone as a predominant Web service design model. In fact, REST has had such a large impact on the Web that it has mostly displaced SOAP- and WSDL-based interface design because its a considerably simpler style to use.
REST didnt attract this much attention when it was first introduced in 2000 by Roy Fielding at the University of California, Irvine, in his academic dissertation, 'Architectural Styles and the Design of Network-based Software Architectures,' which analyzes a set of software architecture principles that use the Web as a platform for distributed computing. Now, years after its introduction, major frameworks for REST have started to appear and are still being developed because its slated, for example, to become an integral part of Javatrade; 6 through JSR-311.
This article suggests that in its purest form today, when its attracting this much attention, a concrete implementation of a REST Web service follows four basic design principles:
- Use HTTP methods explicitly.
- Be stateless.
- Expose directory structure-like URIs.
- Transfer XML, JavaScript Object Notation (JSON), or both.
The following sections expand on these four principles and propose a technical rationale for why they might be important for REST Web service designers.
Use HTTP methods explicitly
One of the key characteristics of a RESTful Web service is the explicit use of HTTP methods in a way that follows the protocol as defined by RFC 2616. HTTP GET, for instance, is defined as a data-producing method thats intended to be used by a client application to retrieve a resource, to fetch data from a Web server, or to execute a query with the expectation that the Web server will look for and respond with a set of matching resources.
REST asks developers to use HTTP methods explicitly and in a way thats consistent with the protocol definition. This basic REST design principle establishes a one-to-one mapping between create, read, update, and delete (CRUD) operations and HTTP methods. According to this mapping:
- To create a resource on the server, use POST.
- To retrieve a resource, use GET.
- To change the state of a resource or to update it, use PUT.
- To remove or delete a resource, use DELETE.
An unfortunate design flaw inherent in many Web APIs is in the use of HTTP methods for unintended purposes. The request URI in an HTTP GET request, for example, usually identifies one specific resource. Or the query string in a request URI includes a set of parameters that defines the search criteria used by the server to find a set of matching resources. At least this is how the HTTP/1.1 RFC describes GET. But there are many cases of unattractive Web APIs that use HTTP GET to trigger something transactional on the server—for instance, to add records to a database. In these cases the GET request URI is not used properly or at least not used RESTfully. If the Web API uses GET to invoke remote procedures, it looks like this:
GET /adduser?name=Robert HTTP/1.1
Its not a very attractive design because the Web method above supports a state-changing operation over HTTP GET. Put another way, the HTTP GET request above has side effects. If successfully processed, the result of the request is to add a new user—in this example, Robert—to the underlying data store. The problem here is mainly semantic. Web servers are designed to respond to HTTP GET requests by retrieving resources that match the path (or the query criteria) in the request URI and return these or a representation in a response, not to add a record to a database. From the standpoint of the intended use of the protocol method then, and from the standpoint of HTTP/1.1-compliant Web servers, using GET in this way is inconsistent.
Beyond the semantics, the other problem with GET is that to trigger the deletion, modification, or addition of a record in a database, or to change server-side state in some way, it invites Web caching tools (crawlers) and search engines to make server-side changes unintentionally simply by crawling a link. A simple way to overcome this common problem is to move the parameter names and values on the request URI into XML tags. The resulting tags, an XML representation of the entity to create, may be sent in the body of an HTTP POST whose request URI is the intended parent of the entity (see Listings 1 and 2).
Listing 1. Before
lt;
剩余内容已隐藏,支付完成后下载完整资料
RESTful风格的Web服务基础
---By Alex Rodriguez 翻译:张崇羿
REST定义了一套针对于系统资源的设计Web服务的架构原则,其中包括了如何解决资源状态和用不同的语言编写的客户端之间的HTTP转换。如果通过使用REST的Web服务的数量来度量,在近几年,REST已经成为一种主流的Web服务设计模型。它对于Web有很大的影响,甚至已经代替了SOAP和基于接口设计的WSDL,因为它拥有一个非常简单的风格。
2000年时,REST由加利福尼亚大学的Roy Fielding在他的学术论文-《构造风格和基于软件结构的网络设计》中第一次提出,他在文中分析了用Web作为平台进行分布式计算的软件架构准则。在被提出多年后的今天,它开始出现在主流的框架中并且还在不断的发展,例如在Javatrade; 6中的JSR-311包完全实现了对REST的支持。
本文建议,在简单形式的今天,REST吸引了这么多的关注,一个REST Web服务在具体实施时应当遵循以下几个设计原则:
- 显式使用HTTP方法
- 无状态
- 公开目录结构的URI
- 传输XML和JSON格式
下面是对四个准则的扩展,从技术和理论上解释它们为什么对REST Web服务设计是最重要的。
显式使用HTTP方法
RESTful Web服务的一个关键特性是以遵循RFC 2616的协议显式使用HTTP方法。例如,HTTP GET被定义为一种数据生成方法,旨在由客户端应用程序检索资源,从Web服务器提取数据,或执行查询,期望Web服务器将查找并使用一组匹配的资源进行响应。
REST要求开发人员以与协议定义一致的方式显式地使用HTTP方法。这种基本的REST设计原则建立了在创建,读取,更新和删除(CRUD)操作和HTTP方法之间的一对一映射。根据该映射:
- 若要在服务器上创建资源,请使用POST。
- 要检索资源,请使用GET。
- 要更改资源的状态或更新资源,请使用PUT。
- 要删除或删除资源,请使用DELETE。
许多Web API中固有的设计缺陷是使用HTTP方法用于非预期目的。例如,HTTP GET请求中的请求URI通常标识一个特定资源。或者,请求URI中的查询字符串包括定义服务器用来查找一组匹配资源的搜索准则的一组参数。至少这是HTTP/1.1 RFC描述GET的方式。但有很多不受欢迎的Web API的情况,使用HTTP GET在服务器上触发事务。例如,向数据库添加记录。在这些情况下,GET请求URI未正确使用或至少未RESTful使用。如果Web API使用GET来调用远程过程,则它如下所示:
GET/adduser?name=Robert HTTP / 1.1
这不是一个非常有吸引力的设计,因为上面的Web方法支持通过HTTP GET的状态改变操作。换句话说,上面的HTTP GET请求有副作用。如果成功处理,请求的结果是添加一个新用户,在这个例子中,Robert到底层数据存储。这里的问题主要是语义。 Web服务器设计为通过检索与请求URI中的路径(或查询条件)匹配的资源来响应HTTP GET请求,并在响应中返回这些或表示,而不是将记录添加到数据库。从当时的协议方法的预期使用的观点来看,并且从HTTP/1.1兼容的Web服务器的观点来看,以这种方式使用GET是不一致的。
除了语义之外,GET的另一个问题是,要触发数据库中记录的删除,修改或添加,或以某种方式更改服务器端状态,它会邀请Web缓存工具(搜寻器)和搜索引擎,无意中通过爬取链接进行服务器端更改。克服这个常见问题的一个简单方法是将请求URI上的参数名称和值移动到XML标记中。生成的标签(要创建的实体的XML表示)可以在HTTP POST的主体中发送,其HTTP请求的URI是实体的预期父级(请参见表1和2)。
表1 前:
1 |
GET /adduser?name=Robert HTTP/1.1 |
1 |
GET /adduser?name=Robert HTTP/1.1 |
表2 后:
1 2 3 4 5 6 7 |
POST /users HTTP/1.1 Host: myserver Content-Type: application/xml lt;?xml version='1.0'?gt; lt;usergt; lt;namegt;Robertlt;/namegt; lt;/usergt; |
上面的方法是RESTful请求的示例:正确使用HTTP POST并在请求的主体中包含有效负载。在接收端,可以通过添加包含在主体中的资源作为在请求URI中标识的资源的下级来处理请求; 在这种情况下,新资源应添加为/users的子级。 在POST请求中指定的新实体与其父实体之间的包含关系类似于文件从属于其父目录的方式。客户端设置实体及其父实体之间的关系,并在POST请求中定义新实体的URI。
然后,客户端应用程序可以使用新的URI获得资源的表示,注意至少在逻辑上资源位于/users下,如表3所示:
表3 HTTP GET请求:
1 2 3 |
GET /users/Robert HTTP/1.1 Host: myserver Accept: application/xml |
以这种方式使用GET是显式的,因为GET仅用于数据检索。GET是一个应该没有副作用的操作,也称为幂等性。
在通过HTTP GET支持更新操作的情况下,也需要应用类似的Web方法重构,如表4所示:
表4 通过HTTP GET更新:
1 |
GET /updateuser?name=Robertamp;newname=Bob HTTP/1.1 |
这将更改资源的名称属性(或属性)。 虽然查询字符串可以用于这样的操作,并且清单4是一个简单的查询字符串,但是当用于更复杂的操作时,这种查询字符串方法签名模式趋于崩溃。因为您的目标是明确使用HTTP方法,更多的RESTful方法是发送一个HTTP PUT请求来更新资源,而不是HTTP GET,出于上述同样的原因(见表5):
表5 HTTP PUT请求:
1 2 3 4 5 6 7 |
PUT /users/Robert HTTP/1.1 Host: myserver Content-Type: application/xml lt;?xml version='1.0'?gt; lt;usergt; lt;namegt;Boblt;/namegt; lt;/usergt; |
使用PUT替换原始资源提供了一个更清洁的接口,这与REST的原则和HTTP方法的定义一致。清单5中的PUT请求是显式的,因为它通过在请求URI中标识该资源来指向要更新的资源,并且在它将一个新的资源表示从客户端传输到PUT主体中的服务器的意义上请求,而不是作为请求URI上的一组松散的参数名称和值来传送资源属性。清单5还具有将资源从Robert重命名为Bob的效果,在这样做时将其URI更改为/users/Bob。在REST Web服务中,使用旧URI的资源的后续请求将生成标准的404 Not Found错误。
作为一般设计原则,它有助于遵循REST准则,通过使用URI中的名词而不是动词明确使用HTTP方法。在RESTful Web服务中,动词-Post,GET,PUT和DELETE已经由协议定义。理想情况下,为了保持接口的一般化并允许客户端显式地调用它们的操作,Web服务不应该定义更多的动词或远程过程,例如/adduser或/updateuser。这个一般设计原则也适用于HTTP请求的主体,其旨在用于传送资源状态,而不携带要调用的远程方法或远程过程的名称。
无状态
REST Web服务需要进行扩展以满足越来越高的性能需求。具有负载平衡和故障转移能力的服务器群集,代理和网关通常以形成服务拓扑的方式布置,这允许根据需要将请求从一个服务器转发到另一个服务器,以减少Web的总体响应时间服务调用。使用中间服务器来提高规模需要REST Web服务客户端发送完整,独立的请求;即发送包括需要满足的所有数据的请求,使得中间服务器中的组件可以转发、路由和负载平衡,而不在请求之间本地保持任何状态。
完整的,独立的请求不需要服务器在处理请求时检索任何种类的应用上下文或状态。 REST Web服务应用程序(或客户端)在请求的HTTP头部和主体内包括服务器端组件生成响应所需的所有参数,上下文和数据。无状态在这个意义上提高了Web服务性能,简化了服务器端组件的设计和实现,因为服务器上没有状态消除了与外部应用程序同步会话数据的需要。
图1示出了有状态服务,应用可以从该状态服务请求多页面结果集中的下一页面,假设该服务在导航该组时跟踪应用程序离开的位置。在这种有状态的设计中,服务递增并存储一个previousPage变量,以便能够响应下一个请求。
图1 有状态设计:
这样的状态服务变得复杂。在Java平台中,企业版(Java EE)环境状态服务需要许多前期考虑,以便跨集群的Java EE容器有效地存储和启用会话数据的同步。在这种类型的环境中,servlet/JavaServer Pages(JSP)和Enterprise JavaBeans(EJB)开发人员很容易发现在会话复制期间找不到java.io.NotSerializableException的根本原因的问题。无论是在HttpSession复制期间被servlet容器抛出还是在有状态的EJB复制期间被EJB容器抛出,这是一个问题,可能会花费开发人员天试图找到一个对象,在一个有时构成服务器的状态的对象的复杂图形中不实现序列化。此外,会话同步会增加开销,这会影响服务器性能。
另一方面,无状态服务器端组件在负载平衡服务器上的设计,写入和分发并不复杂。无状态服务不仅表现更好,而且将维护状态的大部分责任转移到客户端应用程序。在RESTful Web服务中,服务器负责生成响应并提供使客户端能够自己维护应用程序状态的接口。例如,在对多页结果集的请求中,客户端应该包括要检索的实际页码,而不是简单地请求下一页(参见图2)。
图2 无状态设计:
无状态Web服务生成一个响应,该响应链接到集合中的下一个页码,并让客户端执行所需的操作,以保持此值。 RESTful Web服务设计的这一方面可以分解为两组责任,以澄清如何维护无状态服务的高级分离:
服务器
- 生成包含指向其他资源的链接的响应,以允许应用程序在相关资源之间导航。这种类型的响应嵌入链接。类似地,如果请求是针对父资源或容器资源的,那么典型的RESTful响应也可能包括到父级的子级或下级资源的链接,以便这些资源保持连接。
- 通过减少对重复资源的请求数量并完全消除某些请求,生成指示它们是否可缓存的响应,以提高性能。服务器通过包括一个Cache-Control和Last-Modified(一个日期值)HTTP响应头来做到这一点。
客户端应用程序
- 使用Cache-Control响应头来确定是否缓存资源(制作其本地副本)。客户端还读取Last-Modified响应头,并在If-Modified-Since头中发回日期值,以询问服务器资源是否已更改。这称为条件GET,并且两个头部紧密相关,因为服务器的响应是标准304代码(未修改),并且如果从那时起没有改变,则省略请求的实际资源。 304 HTTP响应代码意味着客户端可以安全地使用资源表示形式的缓存的本地副本作为最新的,实际上绕过后续GET请求,直到资源更改。
- 发送可独立于其他请求提供服务的完整请求。这要求客户端充分利用Web服务接口指定的HTTP头,并在请求主体中发送资源的完整表示。客户端发送对先前请求做出非常少的假设的请求,服务器上存在会话,服务器向请求添加上下文的能力或者保持在请求之间的应用状态。
客户端应用程序和服务之间的这种协作对于在RESTful Web服务中是无状态的是至关重要的。它通过节省带宽和最小化服务器端应用程序状态来提高性能。
公开目录结构的URI
从客户端应用程序寻址资源的角度来看,URI决定了REST Web服务的直观性以及服务是否将以设计人员可以预期的方式使用。第三个RESTful Web服务特性是关于URI的。
REST Web服务URI应该直观到易于猜测的点。将URI视为一种自我记录界面,它需要很少的(如果有的话)解释或引用,以便开发人员理解
剩余内容已隐藏,支付完成后下载完整资料
资料编号:[138848],资料为PDF文档或Word文档,PDF文档可免费转换为Word
课题毕业论文、外文翻译、任务书、文献综述、开题报告、程序设计、图纸设计等资料可联系客服协助查找。