SOA专题
使用Apache CXF开发Web服务
SOAP是一个基于XML的信息交换用的应用协议,如HTTP,SMTP等网络协议,作为载体。SOAP消息包括SOAP信封。信封可分为标题和正文。标题包含上下文相关的定义如安全,内容body包含的是实际应用数据。一个典型的SOAP消息看起来像:
<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Header>
</soap:Header>
<soap:Body>
<m:GetStockPrice xmlns:m="http://www.example.org/stock">
<m:StockName>IBM</m:StockName>
</m:GetStockPrice>
</soap:Body>
</soap:Envelope>
WSDL or Web Services 描述语言
WSDL是一个用于描述Web服务的基于XML语言的标准。WSDL完全描述了Web服务公开的公共接口,需要的参数,返回输出结构,Web服务的位置。一个WSDL定义Web服务作为一个集合,这个集合保护能够交换信息的通信端点endpoint。这些通信端点endponit称为端口port。port是由两部分组成的。
1.包含了通过Web服务公开的公共接口。该接口包含所有的方法,所需要的参数来调用和响应返回的结构。
2.绑定公共接口到网络协议像HTTP。绑定信息结合包括像服务的公共接口 消息格式 位置信息。
SOAP联系风格
有两种:
- Document
- RPC
在document中,SOAP消息体中的应用数据作为XML文件的发送,可以被WSDL的XML Schema校验,而XML应该包含web服务开发者的期望结构,以便XML能够被序列化和反序列化传送。
RPC风格顾名思义消费者调用服务的方法好像调用本地方法,为了实现这个RPC,消息是由公共接口的方法组成,使用者可以调用列表。这些方法以名称列表作为XML元素。还有该方法所需参数的方法,这些方法的子方法。序列化和反序列化是由Web框架完成,它含有自己的处理库包。RPC风格导致在应用程序代码和Web服务框架之间的紧密耦合。
服务端代码下载:http://subversion.assembla.com/svn/weblog4j/Weblog4jDemo/trunk
客户端下载:http://subversion.assembla.com/svn/weblog4j/DemoClient/trunk
用Struts2作为依托加入CXF:
我们还是使用使用Apache CXF开发RESTful服务中的书架服务:
创建一个服务端点接口SEI:Service Endpoint Interface
package com.aranin.weblog4j.services;
import com.aranin.weblog4j.vo.BookVO;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService
public interface BookShelfService {
@WebMethod
public String insertBook(BookVO bookVO);
@WebMethod
public BookVO getBook(String title);
}
- @WebService – 这是JAXWS库的元注解.将一个普通的POJO转为普通服务,BookShelfService 不是一个普通接口,而是一个web服务结构SEI。
- @WebMethod – 提供WSDL中公共方法的名称,可选。
实现服务接口:
package com.aranin.weblog4j.services;
import com.aranin.weblog4j.hashdb.HashDB;
import com.aranin.weblog4j.vo.BookVO;
import javax.jws.WebService;
@WebService(endpointInterface = "com.aranin.weblog4j.services.BookShelfService",
serviceName="bookShelfService")
public class BookShelfServiceImpl implements BookShelfService {
public String insertBook(BookVO bookVO) {
HashDB.insertBook(bookVO);
return "Book with name : " + bookVO.getBookName() + " is now available on the shelf"; //To change body of implemented methods use File | Settings | File Templates.
}
public BookVO getBook(String title) {
return HashDB.getBook(title); //To change body of implemented methods use File | Settings | File Templates.
}
}
Spring中的配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxrs
http://cxf.apache.org/schemas/jaxrs.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<jaxws:endpoint
id="bookShelfService"
implementor="com.aranin.weblog4j.services.BookShelfServiceImpl"
address="/bookshelfservice" />
</beans>
服务在http://localhost:8080/weblog4jdemo/bookshelfservice?wsdl
创建调用客户端:
package com.aranin.weblog4j.client;
import com.aranin.weblog4j.services.BookShelfService;
import com.aranin.weblog4j.vo.BookVO;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
public class DemoClient {
public static void main(String[] args){
String serviceUrl = "http://localhost:8080/weblog4jdemo/bookshelfservice";
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(BookShelfService.class);
factory.setAddress(serviceUrl);
BookShelfService bookService = (BookShelfService) factory.create();
//insert book
BookVO bookVO = new BookVO();
bookVO.setAuthor("Issac Asimov");
bookVO.setBookName("Foundation and Earth");
String result = bookService.insertBook(bookVO);
System.out.println("result : " + result);
bookVO = new BookVO();
bookVO.setAuthor("Issac Asimov");
bookVO.setBookName("Foundation and Empire");
result = bookService.insertBook(bookVO);
System.out.println("result : " + result);
bookVO = new BookVO();
bookVO.setAuthor("Arthur C Clarke");
bookVO.setBookName("Rama Revealed");
result = bookService.insertBook(bookVO);
System.out.println("result : " + result);
//retrieve book
bookVO = bookService.getBook("Foundation and Earth");
System.out.println("book name : " + bookVO.getBookName());
System.out.println("book author : " + bookVO.getAuthor());
}
}
输出结果:
INFO: Creating Service {http://services.weblog4j.aranin.com/}BookShelfServiceService from class com.aranin.weblog4j.services.BookShelfService
result : Book with name : Foundation and Earth is now available on the shelf
result : Book with name : Foundation and Empire is now available on the shelf
result : Book with name : Rama Revealed is now available on the shelf
book name : Foundation and Earth
book author : Issac Asimov
Process finished with exit code 0