RESTful Web Services---a very good artical

本文介绍如何使用JAX-WS构建RESTful服务,包括实现和消费RESTful服务的方法,并探讨了RESTful服务的设计考量及描述方式。

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 (Parts 1, 2, and 3). 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 <p>hello world</p>. Note: The URLs provided in this article are for demonstration purposes only and are not live links.

Code Sample 1

@WebServiceProvider
@ServiceMode(value=Service.Mode.PAYLOAD)
public class MyProvider implements Provider<Source> {
public Source invoke(Source source) {
String replyElement = new String("<p>hello world</p>");
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

@javax.xml.ws.WebServiceProvider
@javax.xml.ws.ServiceMode(value=javax.xml.ws.Service.Mode.MESSAGE)
public class PurchaseOrderService implements Provider<Source>{
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
 
 
Table 3
(Click here for 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

Code Fragment 1
(Click here for 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:

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:

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

// T is the message type.
public interface Dispatch<T> {
// synchronous request-response
T invoke(T msg);
// async request-response
Response<T> invokeAsync(T msg);
Future<?> invokeAsync(T msg, AsyncHandler<T> 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:

service = Service.create(qname); 
service.addPort(qname, HTTPBinding.HTTP_BINDING, url);
Dispatch<Source> dispatcher = service.createDispatch(new QName("", ""),
Source.class, Service.Mode.PAYLOAD);
 

The typed Dispatch<T> 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

private void acceptPO() {
Service service = Service.create(qname);
service.addPort(qname, HTTPBinding.HTTP_BINDING, url + "acceptPO");
Dispatch<Source> 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

Code Fragment 3
(Click here for larger sample.)
 

Code Fragment 4 demonstrates how to make a similar PUT request using the Dispatch interface.

Code Fragment 4

Code Fragment 4
(Click here for 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

Code Sample 4
(Click here for larger sample.)
 

Figure 1 shows the display resulting from this code.

Figure 1: Resulting Display
Figure 1: Resulting Display (Click image for larger view.)
 
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

Code Sample 5
(Click here for 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
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.

【语音分离】基于平均谐波结构建模的无监督单声道音乐声源分离(Matlab代码实现)内容概要:本文介绍了基于平均谐波结构建模的无监督单声道音乐声源分离方法,并提供了相应的Matlab代码实现。该方法通过对音乐信号中的谐波结构进行建模,利用音源间的频率特征差异,实现对混合音频中不同乐器或人声成分的有效分离。整个过程无需标注数据,属于无监督学习范畴,适用于单通道录音场景下的语音与音乐分离任务。文中强调了算法的可复现性,并附带完整的仿真资源链接,便于读者学习与验证。; 适合人群:具备一定信号处理基础和Matlab编程能力的高校学生、科研人员及从事音频处理、语音识别等相关领域的工程师;尤其适合希望深入理解声源分离原理并进行算法仿真实践的研究者。; 使用场景及目标:①用于音乐音频中人声与伴奏的分离,或不同乐器之间的分离;②支持无监督条件下的语音处理研究,推动盲源分离技术的发展;③作为学术论文复现、课程项目开发或科研原型验证的技术参考。; 阅读建议:建议读者结合提供的Matlab代码与网盘资料同步运行调试,重点关注谐波建模与频谱分解的实现细节,同时可扩展学习盲源分离中的其他方法如独立成分分析(ICA)或非负矩阵分解(NMF),以加深对音频信号分离机制的理解。
内容概要:本文系统介绍了新能源汽车领域智能底盘技术的发展背景、演进历程、核心技术架构及创新形态。文章指出智能底盘作为智能汽车的核心执行层,通过线控化(X-By-Wire)和域控化实现驱动、制动、转向、悬架的精准主动控制,支撑高阶智能驾驶落地。技术发展历经机械、机电混合到智能三个阶段,当前以线控转向、线控制动、域控制器等为核心,并辅以传感器、车规级芯片、功能安全等配套技术。文中还重点探讨了“智能滑板底盘”这一创新形态,强调其高度集成化、模块化优势及其在成本、灵活性、空间利用等方面的潜力。最后通过“2025智能底盘先锋计划”的实车测试案例,展示了智能底盘在真实场景中的安全与性能表现,推动技术从研发走向市场验证。; 适合人群:汽车电子工程师、智能汽车研发人员、新能源汽车领域技术人员及对智能底盘技术感兴趣的从业者;具备一定汽车工程或控制系统基础知识的专业人士。; 使用场景及目标:①深入了解智能底盘的技术演进路径与系统架构;②掌握线控技术、域控制器、滑板底盘等关键技术原理与应用场景;③为智能汽车底盘研发、系统集成与技术创新提供理论支持与实践参考。; 阅读建议:建议结合实际车型和技术标准进行延伸学习,关注政策导向与行业测试动态,注重理论与实车验证相结合,全面理解智能底盘从技术构想到商业化落地的全过程。
【顶级EI复现】计及连锁故障传播路径的电力系统 N-k 多阶段双层优化及故障场景筛选模型(Matlab代码实现)内容概要:本文介绍了名为《【顶级EI复现】计及连锁故障传播路径的电力系统 N-k 多阶段双层优化及故障场景筛选模型(Matlab代码实现)》的技术资源,重点围绕电力系统中连锁故障的传播路径展开研究,提出了一种N-k多阶段双层优化模型,并结合故障场景筛选方法,用于提升电力系统在复杂故障条件下的安全性与鲁棒性。该模型通过Matlab代码实现,具备较强的工程应用价值和学术参考意义,适用于电力系统风险评估、脆弱性分析及预防控制策略设计等场景。文中还列举了大量相关的科研技术支持方向,涵盖智能优化算法、机器学习、路径规划、信号处理、电力系统管理等多个领域,展示了广泛的仿真与复现能力。; 适合人群:具备电力系统、自动化、电气工程等相关背景,熟悉Matlab编程,有一定科研基础的研究生、高校教师及工程技术人员。; 使用场景及目标:①用于电力系统连锁故障建模与风险评估研究;②支撑高水平论文(如EI/SCI)的模型复现与算法验证;③为电网安全分析、故障传播防控提供优化决策工具;④结合YALMIP等工具进行数学规划求解,提升科研效率。; 阅读建议:建议读者结合提供的网盘资源,下载完整代码与案例进行实践操作,重点关注双层优化结构与场景筛选逻辑的设计思路,同时可参考文档中提及的其他复现案例拓展研究视野。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值