一.为什么要用soap
-
原本我们使用web服务都是根据wsdl生成客户端(生成一堆java文件)然后再调用,本章节讲解如何用soap消息来替代这种方式。
二、SOAP消息格式
- SOAP(简单对象访问协议)是基于XML的消息格式。下面是一个简单的SOAP消息:
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
<soap:Header>
</soap:Header>
<soap:Body>
... message data ...
<soap:Fault>
</soap:Fault>
</soap:Body>
</soap:Envelope>
-
正如你可以看到一个SOAP消息包括:
- Envelope
- Header
- Body
- Message Data
- Fault (optional)
相同的SOAP消息结构用于客户端和Web Service服务器之间的请求和响应。
Body内的Fault元素是可选的。只有Web服务中发生内部错误里才返回。否则,返回正常信息数据。
SOAP不指定一个消息从客户端如何获取到Web Service,但最常见的情况是通过HTTP。
三、案例
3.1 发布服务
- 服务接口
package service;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
@WebService
public interface IFirstService {
@WebResult(name = "addResult")
public int add(@WebParam(name = "x") int x, @WebParam(name = "y") int y);
}
- 服务接口实现类
package service;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
@WebService(endpointInterface = "service.IFirstService")
public class IFirstServiceImpl implements IFirstService {
@Override
public int add(int x, int y) {
return x + y;
}
}
- 发布服务
package publish;
import javax.xml.ws.Endpoint;
import service.IFirstServiceImpl;
public class TestPublish {
public static void main(String[] args) {
Endpoint.publish("http://localhost:3030/first", new IFirstServiceImpl());
System.out.println("发布成功.....");
}
}
- 查看wsdl文件
<definitions targetNamespace="http://service/" name="IFirstServiceImplService">
<types>
<xsd:schema>
<xsd:import namespace="http://service/" schemaLocation="http://localhost:3030/first?xsd=1" />
</xsd:schema>
</types>
<message name="add">
<part name="parameters" element="tns:add" />
</message>
<message name="addResponse">
<part name="parameters" element="tns:addResponse" />
</message>
<portType name="IFirstService">
<operation name="add">
<input wsam:Action="http://service/IFirstService/addRequest"
message="tns:add" />
<output wsam:Action="http://service/IFirstService/addResponse"
message="tns:addResponse" />
</operation>
</portType>
<binding name="IFirstServiceImplPortBinding" type="tns:IFirstService">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
style="document" />
<operation name="add">
<soap:operation soapAction="" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
</binding>
<service name="IFirstServiceImplService">
<port name="IFirstServiceImplPort" binding="tns:IFirstServiceImplPortBinding">
<soap:address location="http://localhost:3030/first" />
</port>
</service>
</definitions>
-
http://localhost:3030/first?xsd=1文件
<xs:schema version="1.0" targetNamespace="http://service/">
<xs:element name="add" type="tns:add" />
<xs:element name="addResponse" type="tns:addResponse" />
<xs:complexType name="add">
<xs:sequence>
<xs:element name="x" type="xs:int" />
<xs:element name="y" type="xs:int" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="addResponse">
<xs:sequence>
<xs:element name="addResult" type="xs:int" />
</xs:sequence>
</xs:complexType>
</xs:schema>
二、客户端发送、接收soap消息
package com.shyroke.webService_client; import java.io.IOException; import java.io.StringReader; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; /** * Hello world! * */ public class App { public static void main(String[] args) { try { /** * 定义发送soap的消息 */ StringBuffer str_xml = new StringBuffer(); str_xml.append( "<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://service/">"); str_xml.append(" <soapenv:Header/>"); str_xml.append(" <soapenv:Body>"); str_xml.append("<ser:add>"); str_xml.append(" <x>11</x>"); str_xml.append("<y>20</y>"); str_xml.append("</ser:add>"); str_xml.append("</soapenv:Body>"); str_xml.append("</soapenv:Envelope>"); /** * 定义post请求 */ // 定义post请求地址 HttpPost httpPost = new HttpPost("http://localhost:3030/first?wsdl"); // 定义post请求的实体 HttpEntity entity = new StringEntity(str_xml.toString()); // 设置post请求的实体和头部 httpPost.setEntity(entity); httpPost.setHeader("Content-Type", "text/xml; charset=UTF-8"); /** * 发送请求并获取返回数据 */ @SuppressWarnings("deprecation") DefaultHttpClient client = new DefaultHttpClient(); // 发送请求并获取返回数据 HttpResponse response = client.execute(httpPost); // 获取返回数据中的实体 HttpEntity respon_entity = response.getEntity(); // 将返回数据的实体转为字符串 String respon_str = EntityUtils.toString(respon_entity); // 解析字符串 SAXReader reader = new SAXReader(); Document document = reader.read(new StringReader(respon_str)); Element rootElement = document.getRootElement(); Element resultElement = rootElement.element("Body").element("addResponse").element("addResult"); String addResult = resultElement.getText(); System.out.println("addResult = " + addResult); } catch (Exception e) { e.printStackTrace(); } } }
结果: