RESTful Web Services(简称REST)是一种基于HTTP协议的Web服务架构风格,它使用标准的HTTP方法(如GET、POST、PUT、DELETE等)来操作资源。REST强调资源的表现形式和状态转移,通过URL来定位资源,通过HTTP动词来描述对资源的操作。
RESTful Web Services的特点包括:
- 无状态性:每个请求都是独立的,不依赖于其他请求,服务器不会保存客户端的状态信息。
- 统一接口:使用标准的HTTP方法进行操作,使得不同的服务之间可以更容易地集成。
- 资源导向:将网络上的资源视为实体,并通过URI来访问和操作这些资源。
- 表现层状态转化:客户端和服务端之间传输的数据格式通常是JSON或XML,便于阅读和解析。
- 可扩展性:由于其简单的设计原则,RESTful Web Services很容易扩展以支持更多的功能或更大的用户量。
RESTful API和SOAP Web服务是两种不同的Web服务架构风格,它们在设计理念、传输协议、数据格式等方面有显著的区别。
-
设计理念:
- RESTful API:基于资源(Resource)的概念,使用HTTP协议进行通信。每个资源通过一个唯一的URI(Uniform Resource Identifier)来标识,并通过HTTP方法(如GET、POST、PUT、DELETE)对资源进行操作。REST强调的是无状态性,即每次请求都是独立的,不依赖于之前的请求。
- SOAP Web服务:基于消息传递的机制,使用XML作为数据格式,并通常使用HTTP或SMTP等协议进行传输。SOAP是一种协议规范,定义了如何封装消息、如何传输以及如何处理错误等。SOAP Web服务通常是有状态的,可以保持会话信息。
-
传输协议:
- RESTful API:主要使用HTTP/HTTPS协议,利用HTTP的方法和状态码来表示操作和响应。
- SOAP Web服务:可以使用多种传输协议,包括HTTP、SMTP、JMS等。
-
数据格式:
- RESTful API:数据格式更加灵活,可以是JSON、XML、纯文本等,但最常用的是JSON。
- SOAP Web服务:数据格式固定为XML,所有消息都必须遵循SOAP协议的规范。
-
安全性:
- RESTful API:安全性依赖于HTTPS和OAuth等机制,也可以通过API网关进行统一管理。
- SOAP Web服务:安全性可以通过WS-Security等标准来实现,提供了更丰富的安全功能。
-
性能:
- RESTful API:由于其轻量级和无状态的特性,通常具有更高的性能和更低的延迟。
- SOAP Web服务:由于其复杂的协议和XML格式,通常会有较高的开销和较长的延迟。
-
适用场景:
- RESTful API:适用于需要高扩展性和灵活性的场景,如移动应用、单页应用(SPA)等。
- SOAP Web服务:适用于需要严格的安全性和事务性的场景,如企业级应用、金融服务等。
By Sameer Tyagi, August 2006
Java
Technical Details
Technical Article
In software engineering, the term software architectural style generally refers to “a set of design rules that identify the kinds of components and connectors that may be used to compose a system or subsystem.” * Some common examples of architectural styles include the Pipe and Filter, Layered, Push Based, and so on. In the web services world, REpresentational State Transfer (REST) is a key design idiom that embraces a stateless client-server architecture in which the web services are viewed as resources and can be identified by their URLs. Web service clients that want to use these resources access a particular representation by transferring application content using a small globally defined set of remote methods that describe the action to be performed on the resource. REST is an analytical description of the existing web architecture, and thus the interplay between the style and the underlying HTTP protocol appears seamless.
The HTTP methods such as GET and POST are the verbs that the developer can use to describe the necessary create, read, update, and delete (CRUD) actions to be performed. Some may see an analogy to operations in SQL, which also relies on a few common verbs, as shown in Table 1. However, the REST style and HTTP protocol are mutually exclusive, and REST does not require HTTP.
Table 1: Relationships Between SQL and HTTP Verbs
Action SQL HTTP
Create Insert PUT
Read Select GET
Update Update POST
Delete Delete DELETE
When to Use REST
Architects and developers need to decide when this particular style is an appropriate choice for their applications. A RESTFul design may be appropriate when
The web services are completely stateless. A good test is to consider whether the interaction can survive a restart of the server.
A caching infrastructure can be leveraged for performance. If the data that the web service returns is not dynamically generated and can be cached, then the caching infrastructure that web servers and other intermediaries inherently provide can be leveraged to improve performance. However, the developer must take care because such caches are limited to the HTTP GET method for most servers.
The service producer and service consumer have a mutual understanding of the context and content being passed along. Because there is no formal way to describe the web services interface, both parties must agree out of band on the schemas that describe the data being exchanged and on ways to process it meaningfully. In the real world, most commercial applications that expose services as RESTful implementations also distribute so-called value-added toolkits that describe the interfaces to developers in popular programming languages.
Bandwidth is particularly important and needs to be limited. REST is particularly useful for limited-profile devices such as PDAs and mobile phones, for which the overhead of headers and additional layers of SOAP elements on the XML payload must be restricted.
Web service delivery or aggregation into existing web sites can be enabled easily with a RESTful style. Developers can use technologies such as Asynchronous JavaScript with XML (AJAX) and toolkits such as Direct Web Remoting (DWR) to consume the services in their web applications. Rather than starting from scratch, services can be exposed with XML and consumed by HTML pages without significantly refactoring the existing web site architecture. Existing developers will be more productive because they are adding to something they are already familiar with, rather than having to start from scratch with new technology.
A SOAP-based design may be appropriate when
A formal contract must be established to describe the interface that the web service offers. The Web Services Description Language (WSDL) describes the details such as messages, operations, bindings, and location of the web service.
The architecture must address complex nonfunctional requirements. Many web services specifications address such requirements and establish a common vocabulary for them. Examples include Transactions, Security, Addressing, Trust, Coordination, and so on. Most real-world applications go beyond simple CRUD operations and require contextual information and conversational state to be maintained. With the RESTful approach, developers must build this plumbing into the application layer themselves.
The architecture needs to handle asynchronous processing and invocation. In such cases, the infrastructure provided by standards such as WSRM and APIs such as JAX-WS with their client-side asynchronous invocation support can be leveraged out of the box.
RESTful Support in JAX-WS
The Java API for XML Web Services (JAX-WS) provides full support for building and deploying RESTful web services. The API was developed through the Java Community Process program as JSR 224. It is tightly integrated with the Java Architecture for XML Binding (JAXB) for binding XML to Java technology data and is included in both the Java Platform, Standard Edition (Java SE) 6 and the Java Platform, Enterprise Edition (Java EE) 5.
Building RESTful Services
The example used in this section builds on the purchase order service described in the Java EE BluePrints catalog as the “Patterns and Design” white papers . The original endpoint contained only one method – acceptPO – that accepted a PurchaseOrder and returned a PurchaseOrderStatus, both of which were defined by individual schemas.
Table 2 shows some more CRUD operations to add to this service.
Table 2: Additional CRUD Operations
Description Java Technology Method Signature
Create a new order public Purchase OrderStatus acceptPO(PurchaseOrder order)
Retrieve an existing order public PurchaseOrder retrievePO (String orderID)
Modify an existing order public PurchaseOrder updatePO(PurchaseOrder order)
Cancel an order already submitted public void cancelPO(String orderID)
JAX-WS enables building RESTful endpoints through a javax.xml.ws.Provider interface in the API. Provider is a generic interface that can be implemented by a class as a dynamic alternative to a service endpoint interface (SEI), and a service implementing this interface can be deployed in a Java EE container or published in a stand-alone mode through the JAX-WS Endpoint API. The Provider interface contains a single method with the following signature:
T invoke(T request)
Provider is a low-level generic API, but using it requires the endpoint to have an intimate knowledge of the desired message or payload structure being passed to the service. Depending on how the provider is implemented, the supported types for T and their uses are the following:
javax.xml.transform.Source . Allows the provider to generate and consume XML directly
javax.activation.DataSource . Works with MIME-typed messages
javax.xml.soap.SOAPMessage . Conveniently works with and manipulates the entire SOAP message
The ServiceMode annotation is used to configure the messaging mode of a Provider instance. With @ServiceMode(value=MESSAGE), the provider will receive and return entire protocol messages – for example, a SOAP message when using the SOAP binding. With @ServiceMode(value=PAYLOAD), the runtime will pass only the message payload on to the provider – for example, the contents of a SOAP Body element when using the SOAP binding. This is useful when you want to build a WSDL-based web service but want to directly access the XML in the payload and return XML directly as well. For details, refer to the “Switching off Data Binding” strategy in this previous article.
Code Sample 1 shows a simple stand-alone provider that, when accessed by browsing to http://127.0.0.1:8084/hello/world, returns the XML message
hello world
. Note: The URLs provided in this article are for demonstration purposes only and are not live links.Code Sample 1
Copy
Copied to Clipboard
Error: Could not Copy
@WebServiceProvider
@ServiceMode(value=Service.Mode.PAYLOAD)
public class MyProvider implements Provider {
public Source invoke(Source source) {
String replyElement = new String(“
hello world
”);StreamSource reply = new StreamSource(
new StringReader(replyElement));
return reply;
}
public static void main(String args[]) {
Endpoint e = Endpoint.create( HTTPBinding.HTTP_BINDING,
new MyProvider());
e.publish(“http://127.0.0.1:8084/hello/world”);
// Run forever e.stop();
}
}
Code Sample 2 shows an extract for the PurchaseOrderService class that implements a Provider interface. The service processes the four main HTTP methods and invokes business operations in their context. Table 3 lists the operation invoked, the sample HTTP request, the HTTP response, and the Java technology method. It is useful – though not required – to include the schemas representing the data exchanged and other documentation with the endpoint Web ARchive (WAR) so that clients can inspect them and reference them as needed.
Code Sample 2
Copy
Copied to Clipboard
Error: Could not Copy
@javax.xml.ws.WebServiceProvider
@javax.xml.ws.ServiceMode(value=javax.xml.ws.Service.Mode.MESSAGE)
public class PurchaseOrderService implements Provider{
private JAXBContext jc;
@javax.annotation.Resource(type=Object.class)
protected WebServiceContext wsContext;
public PurchaseOrderService() {
try {
jc = JAXBContext.newInstance("com.sun.examples.rest");
} catch(JAXBException je) {
throw new WebServiceException("Cannot create JAXBContext", je);
}
}
public Source invoke(Source source) {
try{
MessageContext mc = wsContext.getMessageContext();
String path = (String)mc.get(MessageContext.PATH_INFO);
String method = (String)mc.get(MessageContext.HTTP_REQUEST_METHOD);
if (method.equals(“GET”))
return get(mc);
if (method.equals(“POST”))
return post(source, mc);
if (method.equals(“PUT”))
return put(source, mc);
if (method.equals(“DELETE”))
return delete(source, mc);
throw new WebServiceException(“Unsupported method:” +method);
} catch(JAXBException je) {
throw new WebServiceException(je);
}
}
// Other methods not shown here
With RESTFul web services, there is a natural mapping between the HTTP methods and most CRUD-like business operations that many services expose. Though there are no hard and fast rules, the following general guidelines are applicable for most cases:
GET is used to retrieve data or perform a query on a resource. The data returned from the web service is a representation of the requested resource.
POST is used to create a new resource. The web service may respond with data or status indicating success or failure.
PUT is used to update existing resources or data.
DELETE is used to remove a resource or data.
In some cases, the update and delete actions may be performed with POST operations as well, for example, when the services are consumed by browsers that do not support PUT or DELETE. The GlassFish application server and the JAX-WS API support all four HTTP operations shown in Table 1.
Table 3 shows the HTTP request and HTTP response messages for the operation in the implementation of the purchase order service.
Table 3: HTTP Request and HTTP Response Messages for the Purchase Order Service
(Click herefor larger sample.)
Use cases in which the service needs to indicate an exception can do this by setting the appropriate HTTP status code and response message on the MessageContext. For example, a response to an order retrieval process with an invalid ID can be implemented by setting the HTTP 400 status code and including the XML from the POProcessingProblem.xsd schema. Code Fragment 1 illustrates this.
Code Fragment 1
(Click herefor larger sample.)
Strategy: Implement the verb as part of the URI.
To process a purchase order, make an HTTP request to the URL http://127.0.0.1:8080/restfulwebservice-war/poservice/ acceptPO
The service or resource interprets the verb in the URI as the action that it must perform. The service retrieves the necessary data from the request, which physically can be an HTTP GET or POST, and it returns data based on the PurchaseOrder.xsd schema.
Strategy: Use the protocol method to describe the verb or operation.
To retrieve a purchase order in which the order ID is ABC123, make an HTTP request using a GET operation. In this case, the requested URL would be http://127.0.0.1:8080/restfulwebservice-war/poservice/ABC123
Following is a sample HTTP request:
Copy
Copied to Clipboard
Error: Could not Copy
GET /restfulwebservice-war/poservice/ABC123 HTTP/1.0
Accept-Language: en-us
Connection: close
Content-Type: text/xml
Host: 127.0.0.1:9090
To cancel a purchase order in which an order ID is ABC123, make an HTTP request using a DELETE operation. In this case, the URL would also be http://127.0.0.1:8080/restfulwebservice-war/poservice/ABC123
Following is a sample HTTP request:
Copy
Copied to Clipboard
Error: Could not Copy
DELETE /restfulwebservice-war/poservice/ABC123 HTTP/1.0
Accept-Language: en-us
Connection: close
Content-Type: text/xml
Host: 127.0.0.1:9090
Pragma: no-cache
Consuming RESTful Services
Applications can access RESTful services in one of two ways: programmatically or by using browsers.
Accessing Services Programmatically
JAX-WS enables a client to consume RESTful web services programmatically. The main API is the javax.xml.ws.Dispatch interface described in Code Sample 3.
Code Sample 3
Copy
Copied to Clipboard
Error: Could not Copy
// T is the message type.
public interface Dispatch {
// synchronous request-response
T invoke(T msg);
// async request-response
Response invokeAsync(T msg);
Future<?> invokeAsync(T msg, AsyncHandler h);
// one-way
void invokeOneWay(T msg);
}
Unlike the Provider on the server side, developers don’t actually implement this API. Instead, they obtain an instance from the Service object as shown here:
Copy
Copied to Clipboard
Error: Could not Copy
service = Service.create(qname);
service.addPort(qname, HTTPBinding.HTTP_BINDING, url);
Dispatch dispatcher = service.createDispatch(new QName(“”, “”),
Source.class, Service.Mode.PAYLOAD);
The typed Dispatch interface and the invoke method can accept and return four major datatypes:
Dispatch<javax.xml.transform.Source> . Useful for HTTP binding payload mode
Dispatch<javax.xml.soap.SOAPMessage> . Useful for SOAP message mode
Dispatch<javax.activation.DataSource> . Useful for handling MIME messages
Dispatch<Object> . Useful for payload mode with JAXB binding
Code Fragment 2 demonstrates how to make a POST request to http://127.0.0.1:8080/restfulwebservice-war/poservice/acceptPO with the XML as the body of the POST request read from a string.
Code Fragment 2
Copy
Copied to Clipboard
Error: Could not Copy
private void acceptPO() {
Service service = Service.create(qname);
service.addPort(qname, HTTPBinding.HTTP_BINDING, url + “acceptPO”);
Dispatch dispatcher = service.createDispatch(qname,
Source.class, Service.Mode.MESSAGE);
Map<String, Object> requestContext = dispatcher.getRequestContext();
requestContext.put(MessageContext.HTTP_REQUEST_METHOD, “POST”);
Source result = dispatcher.invoke(new StreamSource(new StringReader(poXML)));
printSource(result);
}
Code Fragment 3 demonstrates how to make a similar POST request, but it differs from Code Fragment 2 in that it sends and returns JAXB-generated objects rather than handling strings directly.
Code Fragment 3
(Click herefor larger sample.)
Code Fragment 4 demonstrates how to make a similar PUT request using the Dispatch interface.
Code Fragment 4
(Click herefor larger sample.)
Accessing Services Using Browsers
Because RESTful web services deployed in JAX-WS are exposed using the standard HTTP protocol and methods, they can be easily accessed from browsers. In addition to using simple GET and POST requests directly from browsers, developers can leverage the capabilities of the JavaScript technology XMLHttpRequest object that most modern browsers support. This is the same object used for building AJAX user interfaces (UIs).
Code Sample 4 shows a simple script that is included with the downloadable sample code and test client that you can use to test RESTful web services from browsers.
Code Sample 4
(Click herefor larger sample.)
Figure 1 shows the display resulting from this code.
(Click herefor larger sample.)
Figure 1: Resulting Display
Describing RESTful Endpoints
Unlike SOAP-based web services, which have a standard vocabulary to describe the web service interface through WSDL, RESTful web services currently have no such grammar. For a service consumer to understand the context and content of the data that must be sent to and received from the service, both the service consumer and service producer must have an out-of-band agreement. This takes the form of documentation, sample code, and an API that the service provider publishes for developers to use. For example, the many web-based services available from Google, Yahoo, Flickr, and so on have accompanying artifacts describing how to consume the services.
If you are developing RESTful web services, the following general guidelines provide a good starting point:
Make the XML schemas available to service consumers and package them with the WAR file.
Clearly document the expected input, output, and error conditions that may arise as result of invocation.
Web Application Description Language (WADL)
The style of documenting RESTful web services that this article has previously described is fine for use by developers, but it prevents tools from programmatically consuming such services and generating artifacts specific to programming languages. For example, a WSDL file can be consumed by various tools and proxies or by generated stubs that applications can use directly. A research effort from Sun Labs called Web Application Description Language (WADL)attempts to resolve some of these issues by providing a means to describe services in terms of schemas, HTTP methods, and the request or response structures exchanged. The schema in Code Sample 5 shows a sample WADL description for the example discussed previously.
Code Sample 5
(Click herefor larger sample.)
Summary
JAX-WS provides comprehensive support for building web services. Developers can leverage the capabilities of this API to build and consume a variety of web services, whether those services are based on WSDL or are RESTful in behavior. The combination of the Provider and Dispatch interfaces allows web services to be built and consumed, and it provides developers with the flexibility to process the messages sent over the wire in a variety of ways. In addition, the future holds the possibility of describing RESTful web services for tools to consume, which will further simplify the developer’s experience.
For More Information
Toward Boxology: Preliminary Classification of Architectural Styles, by M. Shaw and P. Clements
Architectural Styles and the Design of Network-based Software Architectures, by Roy Thomas Fielding
Java API for XML Web Services (JAX-WS)
JSR 224: Java API for XML-Based Web Services (JAX-WS) 2.0
Web Application Description Language (WADL)
About the Author
Sameer Tyagi is a senior staff engineer at Sun Microsystems with the Web Services group. He remains focused on architecture, design, and implementation of large-scale enterprise applications with Java technology. Among his publications are industry periodicals and books on Java and Java EE technologies, as well as a blog.