Apache CXF实现Web Service(2)——不借助重量级Web容器和Spring实现一个纯的JAX-RS(RESTful) web service

实现目标

http://localhost:9000/rs/roomservice 为入口, 
http://localhost:9000/rs/roomservice/room为房间列表, 
http://localhost:9000/rs/roomservice/room/001/ 为001号房间的信息, 
http://localhost:9000/rs/roomservice/room/001/person 为在001号房间主的人的列表

在Eclipse中新建一个Java Project

(可以不是WTP的Dynamic Web Project)参考文章:Apache CXF实现Web Service(1)中的介绍

再看pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.cnblog.richaaaard.cxfstudy</groupId>
    <artifactId>cxf-test-standalone-rs-helloworld</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>cxf-test-standalone-rs-helloworld Maven Webapp</name>
    <url>http://maven.apache.org</url>  

    <properties>
<!--         <cxf.version>2.7.18</cxf.version> -->
        <cxf.version>3.1.4</cxf.version>
    </properties>  

    <dependencies>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http</artifactId>
            <version>${cxf.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http-jetty</artifactId>
            <version>${cxf.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-ws-security</artifactId>
            <version>${cxf.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-ws-policy</artifactId>
            <version>${cxf.version}</version>
        </dependency>
<!--         <dependency>   -->
<!--             <groupId>org.apache.cxf</groupId>   -->
<!--             <artifactId>cxf-bundle-jaxrs</artifactId>   -->
<!--             <version>${cxf.version}</version>   -->
<!--         </dependency>   -->
 	<dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
            <version>${cxf.version}</version>
        </dependency>
        <dependency>
            <groupId>javax.ws.rs</groupId>
            <artifactId>jsr311-api</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.5.8</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.5.8</version>
        </dependency>
        <dependency>
            <groupId>commons-httpclient</groupId>
            <artifactId>commons-httpclient</artifactId>
            <version>3.0</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.3</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.8.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>  

    <build>
        <finalName>cxfstudy</finalName>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**</include>
                </includes>
                <excludes>
                    <exclude>**/*.java</exclude>
                </excludes>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.mortbay.jetty</groupId>
                <artifactId>maven-jetty-plugin</artifactId>
                <configuration>
                    <contextPath>/</contextPath>
                    <connectors>
                        <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
                            <port>9000</port>
                        </connector>
                    </connectors>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
        </plugins>
    </build>  

</project>

  与(1)中介绍的类同,JAXRSServerFactoryBean存在于cxf-rt-frontend-jaxrs中,而集合包cxf-bundle-jaxrs是不必要的

供资源使用的实体类Room和Person

package com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.model;

import java.util.HashMap;
import java.util.Map;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="Room")
public class Room {
    public Room()
    {
        persons=new HashMap<String,Person>();
    }
    String id;
    Map<String,Person> persons;  

    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public Map<String, Person> getPersons() {
        return persons;
    }
    public void setPersons(Map<String, Person> persons) {
        this.persons = persons;
    }
}

  注意不要漏掉@XmlRootElement

package com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.model;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="Person")
public class Person {
    private String name;
    private String sex;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }  

}

  为了解决“No message body writer found for class”,即非简单对象无法序列化的问题,我们暂时先加两个Wrapper类作为Room的集合类和Person集合类,后面会专门介绍如何更优雅的解决这个问题。

Rooms.java

 1 package com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.model;
 2
 3 import java.util.Map;
 4
 5 import javax.xml.bind.annotation.XmlRootElement;
 6
 7 import com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.dao.RoomDAO;
 8
 9 @XmlRootElement(name="rooms")
10 public class Rooms {
11     Map<String,Room> rooms;
12     public Rooms()
13     {
14         rooms=RoomDAO.getMapOfRooms();
15     }
16     public Map<String, Room> getRooms() {
17         return rooms;
18     }
19     public void setRooms(Map<String, Room> rooms) {
20         this.rooms = rooms;
21     }
22 }  

Persons.java

package com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.model;

import java.util.Map;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="persons")
public class Persons {
    Map<String,Person> persons;
    public Persons()
    {
        persons=null;
    }
    public Persons(Room room)
    {
        persons=room.getPersons();
    }
    public Map<String, Person> getPersons() {
        return persons;
    }
    public void setPersons(Map<String, Person> persons) {
        this.persons = persons;
    }
}  

实体有了,需要数据,我们虚拟了一个DAO(原本DAO是数据访问层),这里我们直接将所需要测试的数据创建其中

 1 package com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.dao;
 2
 3 import java.util.HashMap;
 4 import java.util.Map;
 5
 6 import com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.model.Person;
 7 import com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.model.Room;
 8 import com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.model.Rooms;
 9
10 public class RoomDAO {
11     private static Map<String, Room> rooms;
12     static {
13         rooms = new HashMap<String, Room>();
14
15         Person p1=new Person();
16         p1.setName("Boris");
17         p1.setSex("male");
18
19
20
21         Room r=new Room();
22         r.setId("001");
23         r.getPersons().put(p1.getName(), p1);
24         rooms.put("001", r);
25     }
26
27     public static void addRoom(Room room) {
28         rooms.put(room.getId(), room);
29     }
30
31     public static void deleteRoom(String id) {
32         if (rooms.containsKey(id)) {
33             rooms.remove(id);
34         }
35
36     }
37
38     public static void updateRoom(String id,Room room) {
39         rooms.remove(id);
40         rooms.put(room.getId(), room);
41     }
42
43     public static Room getRoom(String id) {
44         if (rooms.containsKey(id)) {
45             return rooms.get(id);
46         } else {
47             return null;
48         }
49     }
50     /*operations to persons*/
51     public static void addPerson(String id_room,Person person) {
52         if(rooms.containsKey(id_room))
53         {
54             Room room=rooms.get(id_room);
55             room.getPersons().put(person.getName(), person);
56         }
57     }
58
59     public static Rooms getRooms()
60     {
61         return new Rooms();
62     }
63
64     public static void deletePerson(String id_room,String name)
65     {
66         if(rooms.containsKey(id_room))
67         {
68             Room room=rooms.get(id_room);
69             room.getPersons().remove(name);
70         }
71     }
72
73     public static Map<String, Room> getMapOfRooms()
74     {
75         return rooms;
76     }
77 }  

到这里,我们基本已经完成准备工作

那么如何写一个RESTful Web Service呢?

package com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.service;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;

import com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.dao.RoomDAO;
import com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.model.Person;
import com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.model.Persons;
import com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.model.Room;
import com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.model.Rooms;

@Path("/roomservice")
@Produces("application/xml")
public class RoomService {  

    @GET
    @Path("/room/{id}")
    @Consumes("application/xml")
    public Room getRoom(@PathParam("id")String id )
    {
        System.out.println("get room by id= "+id);
        Room room=RoomDAO.getRoom(id);
        return room;
    }
    @GET
    @Path("/room")
    @Consumes("application/xml")
    public Rooms getAllRoom()
    {
        System.out.println("get all room");
        Rooms rooms=RoomDAO.getRooms();
        return rooms;
    }  

    @POST
    @Path("/room")
    @Consumes("application/xml")
    public void addRoom(Room room)
    {
        System.out.println("add room which id is:"+room.getId());
        RoomDAO.addRoom(room);
    }
    @PUT
    @Path("/room/{id}")
    @Consumes("application/xml")
    public void updateRoom(@PathParam("id")String id,Room room)
    {
        System.out.println("update room which original id is:"+room.getId());
        RoomDAO.updateRoom(id,room);
    }
    @DELETE
    @Path("/room/{id}")
    @Consumes("application/xml")
    public void deleteRoom(@PathParam("id")String id)
    {
        System.out.println("remove room by id= "+id);
        RoomDAO.deleteRoom(id);
    }
    @POST
    @Path("/room/{id}")
    @Consumes("application/xml")
    public void addPerson(@PathParam("id") String id,Person person)
    {
        System.out.println("add person who‘s name is:"+person.getName());
        RoomDAO.addPerson(id, person);
    }  

    @GET
    @Path("/room/{id}/person")
    @Consumes("application/xml")
    public Persons getAllPersonOfRoom(@PathParam("id") String id)
    {
//         System.out.println("get room by id= "+id);
//         Room room=RoomDAO.getRoom(id);
//         return room.getPersons();
//        TODO No message body writer HashMap
         System.out.println("get room by id= "+id);
         Room room=RoomDAO.getRoom(id);
         return new Persons(room);
    }  

    @DELETE
    @Path("/room/{id}/{name}")
    @Consumes("application/xml")
    public void deletePerson(@PathParam("id")String id,@PathParam("name")String name)
    {
        System.out.println("remove person who‘s name is: "+name);
        RoomDAO.deletePerson(id, name);
    }
}  

注意在类头上的Annotation @Path和@Produces

@Path("/roomservice")——指这个服务的根路径,用于区分其他服务

@Produces("application/xml")——指这个服务生产xml的响应

最后我们还需一个服务

我们使用与(1)类似的方法,用JAXRSServerFactoryBean来启动一个服务

package com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.server;

import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;

import com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.model.Person;
import com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.model.Persons;
import com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.model.Room;
import com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.model.Rooms;
import com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.service.RoomService;

public class Server {  

    public static void main(String[] args) {
        RoomService service = new RoomService();  

        // Service instance
        JAXRSServerFactoryBean restServer = new JAXRSServerFactoryBean();
        restServer.setResourceClasses(Room.class, Person.class, Rooms.class, Persons.class);
        restServer.setServiceBean(service);
        restServer.setAddress("http://localhost:9000/rs");
        restServer.create();
    }
} 

运行服务Run As... -> Java Application

124 [main] WARN org.apache.cxf.jaxrs.utils.ResourceUtils - No resource methods have been found for resource class com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.model.Room
124 [main] WARN org.apache.cxf.jaxrs.utils.ResourceUtils - No resource methods have been found for resource class com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.model.Person
125 [main] WARN org.apache.cxf.jaxrs.utils.ResourceUtils - No resource methods have been found for resource class com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.model.Rooms
125 [main] WARN org.apache.cxf.jaxrs.utils.ResourceUtils - No resource methods have been found for resource class com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.model.Persons
222 [main] INFO org.apache.cxf.endpoint.ServerImpl - Setting the server‘s publish address to be http://localhost:9000/rs
284 [main] INFO org.eclipse.jetty.util.log - Logging initialized @500ms
318 [main] INFO org.eclipse.jetty.server.Server - jetty-9.2.11.v20150529
330 [main] WARN org.eclipse.jetty.server.handler.AbstractHandler - No Server set for [email protected]02ad
357 [main] INFO org.eclipse.jetty.server.ServerConnector - Started [email protected]{HTTP/1.1}{localhost:9000}
357 [main] INFO org.eclipse.jetty.server.Server - Started @582ms
362 [main] WARN org.eclipse.jetty.server.handler.ContextHandler - Empty contextPath
369 [main] INFO org.eclipse.jetty.server.handler.ContextHandler - Started [email protected]{/,null,AVAILABLE}

  暂时忽略WARN里面的日志

然后我们通过浏览器测试

(测试方式有多种,原则上能对http Interceptor的工具都可以对web service进行测试,eclipse里有自带的工具,TcpTrace、SoapUI也都是比较好用的小工具)

*扩展,RESTful用json格式

我们将RoomService.java中所有的"application/xml"替换成"application.json",然后重启服务。

浏览器访问会出现一行错误提示

"

No message body writer has been found for class com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.model.Rooms, ContentType: application/json

"

这是因为,CXF默认有xml的序列化provider,我们需要显性指定一个JsonProvider,这里我们先用一个业界比较流行的Jackson来支持。

先在pom中加入依赖

<dependency>
  <groupId>com.fasterxml.jackson.jaxrs</groupId>
  <artifactId>jackson-jaxrs-json-provider</artifactId>
  <version>2.6.3</version>
</dependency>

然后为我们的server实例指定一个JsonProvider: JacksonJsonProvider

package com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.server;

import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;

import com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.model.Person;
import com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.model.Persons;
import com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.model.Room;
import com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.model.Rooms;
import com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.service.RoomService;
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;

public class Server {  

    public static void main(String[] args) {
        RoomService service = new RoomService();  

        // Service instance
        JAXRSServerFactoryBean restServer = new JAXRSServerFactoryBean();
        restServer.setResourceClasses(Room.class, Person.class, Rooms.class, Persons.class);
        restServer.setServiceBean(service);
        restServer.setAddress("http://localhost:9000/rs");
        restServer.setProvider(new JacksonJsonProvider());
        restServer.create();
    }
} 

返回浏览器,访问地址:http://localhost:9000/rs/roomservice/room 查看,这时我们看到json格式的数据正常返回了。

追问:如果我们用cxf自己的JSONProvider会怎样?

如果用cxf自己的JSONProvider,我们需要引入

cxf-rt-rs-extension-providers.jar

而这个jar在运行时还会依赖jettison里面的TypeConverter,所以我们需要引入

jettison.jar

<dependency>
    <groupId>org.apache.cxf</groupId>
  <artifactId>cxf-rt-rs-extension-providers</artifactId>
  <version>${cxf.version}</version>
</dependency>

<dependency>
  <groupId>org.codehaus.jettison</groupId>
  <artifactId>jettison</artifactId>
  <version>1.3.7</version>
</dependency>

完事之后将Server里面的Provider换掉

package com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.server;

import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.apache.cxf.jaxrs.provider.json.JSONProvider;

import com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.model.Person;
import com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.model.Persons;
import com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.model.Room;
import com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.model.Rooms;
import com.cnblog.richaaaard.cxftest.standalone.rs.helloworld.service.RoomService;

public class Server {

    public static void main(String[] args) {
        RoomService service = new RoomService();

        // Service instance
        JAXRSServerFactoryBean restServer = new JAXRSServerFactoryBean();
        restServer.setResourceClasses(Room.class, Person.class, Rooms.class, Persons.class);
        restServer.setServiceBean(service);
        restServer.setAddress("http://localhost:9000/rs");
//        restServer.setProvider(new JacksonJsonProvider());
        restServer.setProvider(new JSONProvider<Object>());
        restServer.create();
    }
}

从浏览器访问,也同样得到了序列化的json:

不知道有没有人注意两个json string不太一样。这是因为不同库的实现方式不同,Jettison生成的字符串明显≥Jackson的实现。

那么问题来了

如何选择json的实现呢?在实际应用中,xml好还是json或是其他格式会更好呢?

  

 

参考:

http://www.cnblogs.com/ggjucheng/p/3352477.html

https://cwiki.apache.org/confluence/display/CXF20DOC/JAXRS+Services+Configuration

时间: 2024-10-24 10:21:50

Apache CXF实现Web Service(2)——不借助重量级Web容器和Spring实现一个纯的JAX-RS(RESTful) web service的相关文章

分享一个Android和java调用RESTful Web服务的利器Resting

分享一个Android和java调用RESTful Web服务的利器Resting 当我们调用Web服务,往往是最终目标是取HTTP响应,将其转化为将在应用中呈现的值对象.Resting可以用来实现这一功能.Resting,在Java的一个轻量级的REST框架,可用于调用一个RESTful Web服务,并转换成响应来自客户端应用程序定制的Java对象.由于它的简单,resting是适合Android等手持设备. resting目标?暴露简单的get(),post(),put()和delete()

Spring起步(一)Building a RESTful Web Service

http://spring.io/guides/gs/rest-service/ 先放链接. 这个很小很小的一个功课,我却遇到了各种各样的奇葩错误,折腾了两天才弄好. 想要开始的话,需要一些准备工具 1.maven(不推荐gradle,运行的时候会自动FQ然后失败) 2.sts(不推荐在eclipse上装,因为会非常非常卡,推荐直接从spring官网上下已经集成好的版本) 在官网上分别给出了maven和gradle的使用方法,但就是没有说sts应该怎么运行于是我折腾搜索了很久才找到方法. sts

Apache CXF实现Web Service(3)——Tomcat容器和不借助Spring的普通ServletJAX-RS(RESTful) web service

起步 参照这一系列的另外一篇文章: Apache CXF实现Web Service(2)——不借助重量级Web容器和Spring实现一个纯的JAX-RS(RESTful) web service 首先在eclipse中新建一个Dynamic Web Project,然后实现上篇文章中的所有类,唯一不同的是这里,我们不需要一个Server.java来启动一个Web Service.我们用CXF自带的org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServ

Apache CXF实现Web Service(4)——Tomcat容器和Spring实现JAX-RS(RESTful) web service

准备 我们仍然使用 Apache CXF实现Web Service(2)——不借助重量级Web容器和Spring实现一个纯的JAX-RS(RESTful) web service 中的代码作为基础,并引入spring来进行RESTful web service的配置和管理. 项目目录结构如下图 首先我们要在web.xml中加入通过Spring的ContextLoaderListener加载的Spring运行时环境以及CXF的Spring配置文件 web.xml <?xml version="

Apache CXF实现WebService入门教程(附完整源码)

Apache CXF实现WebService非常简单实用,只需要几步就可以实现一个简单的web service. 首先我们需要新建一个maven项目,在pom中添加依赖和jetty作为测试的web service的web容器. 如下是测试用到的pom文件内容: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance&qu

Apache CXF 103 CXF Basics - partial

0 引言 0.1 基本的Web服务术语 XML 业界的结构化交换信息表示的事实上的标准. XML namespace是在XML文档中提供唯一的命名元素和属性的标准. XML schema提供了定义XML文档结构.内容和语义的方法. SOAP(Simple Object Access Protocol) SOAP是在网络环境中交换XML消息的协议,通常使用HTTP协议. SOAP消息格式是SOAP信封.SOAP信封包含了所有请求消息,由可选头部和体构成. SOAP信封头部可选的包含上下文相关信息,

Apache CXF 102 CXF with REST

前言 续上篇Apache CXF 101,摘抄部分REST概念性知识,以运行实例考察CXF对REST的支持. 目录 1 REST简介 2 工具 3 运行实例 内容 本Spike记录中内容,如无特别指出,均引用[1]. 1 REST简介 有两种实现Web Service的主要方式:SOAP(Simple Object Access Protocl)和REST架构风格(Representational State Transfer architecture style). 用REST架构风格构建的服

基于jersey和Apache Tomcat构建Restful Web服务(一)

基于jersey和Apache Tomcat构建Restful Web服务(一) 现如今,RESTful架构已然成为了最流行的一种互联网软件架构,它结构清晰.符合标准.易于理解.扩展方便,所以得到越来越多网站的采用.那么问题来了,它是什么呢? 起源 REST(Representational state transfer)在 2000 年由 Roy Fielding 在博士论文中提出,他是 HTTP 规范 1.0 和 1.1 版的首席作者之一. REST 中最重要的概念是资源(resources

Restful Web Service初识

Restful Web Service初识 一.Web Services Web Services 是一种基于组件的软件平台,是面向服务的Internet 应用.Web Services 框架的核心技术包括SOAP ,WSDL 和UDDI ,它们都是以标准的XML 文档的形式表示. SOAP (“Simple Object Access Protocol”的缩写)是Web Services 的通信协议.SOAP是一种简单的.轻量级的基于XML 的机制,用于在网络应用程序之间进行结构化数据交换.S