SOAP 教程
SOAP 教程
SOAP(Simple Object Access Protocol,简单对象访问协议)是 W3C 制定的基于 XML 的消息交换协议,用于分布式环境中应用程序之间的通信,是传统 Web 服务(WS-*)的核心标准。
核心特点
- 基于 XML:消息格式标准,跨语言跨平台
- 独立传输:可运行于 HTTP、SMTP、TCP 等协议之上
- 强类型:通过 WSDL 描述接口契约
- 安全标准成熟:WS-Security 支持加密与签名
- 状态无关:无状态协议,每个消息独立处理
消息结构
<soap:Envelope> <!-- 根元素 --> <soap:Header> <!-- 可选,元数据 --> </soap:Header> <soap:Body> <!-- 必选,实际数据 --> </soap:Body> </soap:Envelope>
学习路线
- 简介与语法
- Envelope / Header / Body / Fault 元素
- HTTP Binding
- 实例、总结
SOAP 简介
SOAP 简介
1. 历史背景
1998 年 由 Microsoft、DevelopMentor 提出 2000 年 W3C 接管,成为 Web 服务标准 2003 年 SOAP 1.2 成为 W3C 推荐标准 2007 年 SOAP 1.2 第二版 # 注:SOAP 1.2 后不再扩展缩写含义
2. 为什么用 SOAP
- 企业级应用集成(异构系统通信)
- 严格的接口契约(WSDL)
- 安全与事务需求(WS-Security、WS-Transaction)
- 语言无关(Java/C#/Python 互通)
3. SOAP vs REST
| 对比项 | SOAP | REST |
|---|---|---|
| 数据格式 | XML | JSON/XML |
| 协议 | HTTP/SMTP/TCP | HTTP |
| 接口契约 | WSDL(强) | OpenAPI(可选) |
| 学习曲线 | 陡 | 平缓 |
| 性能 | 消息大,慢 | 轻量,快 |
| 适用 | 企业金融级 | 互联网应用 |
4. 典型场景
- 银行、支付系统集成
- 电信运营商 BSS/OSS
- 传统 ERP/CRM 对接
- 跨企业 B2B 交易
SOAP 语法
SOAP 语法
1. 基本语法规则
# SOAP 消息必须使用 XML 编码
# 必须使用 SOAP Envelope 命名空间
# 必须使用 XML 编码(不能省略 Envelope/Body)
# 不能包含 DTD 或 XML 处理指令
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
<soap:Body>
<m:GetPrice xmlns:m="http://example.com/ws">
<m:Item>Apples</m:Item>
</m:GetPrice>
</soap:Body>
</soap:Envelope>
2. 命名空间
# SOAP 1.1 http://schemas.xmlsoap.org/soap/envelope/ # SOAP 1.2 http://www.w3.org/2003/05/soap-envelope # 编码规范 SOAP 1.1: http://schemas.xmlsoap.org/soap/encoding/ SOAP 1.2: http://www.w3.org/2003/05/soap-encoding # 业务命名空间(自定义) xmlns:m="http://example.com/ws"
3. 结构要求
# Envelope # - 根元素,标识 SOAP 消息 # - 必须包含 Body # Header(可选) # - 携带认证、事务等元信息 # Body(必选) # - 包含实际请求/响应数据 # - 或包含 Fault(错误) # Fault(错误时出现) # - 位于 Body 内 # - 描述错误信息
4. 编码风格
# encodingStyle 指定编码规则 soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding" # 数组编码 <tns:numbers soap:arrayType="xsd:int[3]"> <tns:int>1</tns:int> <tns:int>2</tns:int> <tns:int>3</tns:int> </tns:numbers>
SOAP Envelope 元素
SOAP Envelope 元素
1. Envelope 定义
# Envelope 是 SOAP 消息的根元素 # 标识文档为 SOAP 消息 <?xml version="1.0"?> <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"> ... </soap:Envelope>
2. 命名空间要求
# 必须正确使用命名空间 # SOAP 1.1 <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> # SOAP 1.2 <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"> # 错误命名空间会报 VersionMismatch 错误
3. 结构规则
# 结构 Envelope ├── Header(可选,可多个) └── Body(必须,且只一个) # 规则 - Header 必须在 Body 之前 - Body 最多一个 - Envelope 内容不能包含额外顶层元素
4. 完整示例
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:m="http://example.com/order">
<soap:Header>
<m:Auth>
<m:Token>abc123</m:Token>
</m:Auth>
</soap:Header>
<soap:Body>
<m:CreateOrder>
<m:Item>Laptop</m:Item>
<m:Quantity>2</m:Quantity>
</m:CreateOrder>
</soap:Body>
</soap:Envelope>
SOAP Header 元素
SOAP Header 元素
1. Header 作用
# Header 是可选的,用于携带消息的"附加信息" # 常见用途: - 认证信息(Token、用户名密码) - 事务标识 - 消息路由信息 - 优先级 - 版本信息
2. 基本用法
<soap:Header>
<m:Auth xmlns:m="http://example.com/auth">
<m:Username>admin</m:Username>
<m:Password>secret</m:Password>
</m:Auth>
</soap:Header>
3. Header 属性
# mustUnderstand:接收方必须处理 <m:Auth soap:mustUnderstand="1"> # 接收方不理解该 header 时报 Fault # actor(SOAP 1.1)/role(SOAP 1.2) # 指定处理该 header 的节点 <m:Log soap:actor="http://example.com/log"> # relay(SOAP 1.2) # 是否可传递给下游节点 <m:Info soap:relay="true">
4. 认证 Header 示例
<soap:Header>
<wsse:Security
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken>
<wsse:Username>api_user</wsse:Username>
<wsse:Password Type="PasswordText">pass123</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soap:Header>
5. 事务 Header 示例
<soap:Header>
<t:Transaction
xmlns:t="http://example.com/transaction"
soap:mustUnderstand="1">
<t:TransactionID>TX-20260818-001</t:TransactionID>
</t:Transaction>
</soap:Header>
SOAP Body 元素
SOAP Body 元素
1. Body 作用
# Body 是必选元素,包含消息的实际内容 # - 请求:调用的方法及其参数 # - 响应:方法返回的数据 # - 错误:Fault 元素
2. 请求示例
<soap:Body>
<m:GetPrice xmlns:m="http://example.com/ws">
<m:Item>Apples</m:Item>
</m:GetPrice>
</soap:Body>
3. 响应示例
<soap:Body>
<m:GetPriceResponse xmlns:m="http://example.com/ws">
<m:Price>1.50</m:Price>
<m:Currency>USD</m:Currency>
</m:GetPriceResponse>
</soap:Body>
4. 复杂数据类型
<soap:Body>
<m:CreateOrder xmlns:m="http://example.com/order">
<m:Order>
<m:Customer>
<m:Name>张三</m:Name>
<m:Email>zhang@example.com</m:Email>
</m:Customer>
<m:Items>
<m:Item>
<m:Product>Laptop</m:Product>
<m:Qty>1</m:Qty>
</m:Item>
<m:Item>
<m:Product>Mouse</m:Product>
<m:Qty>2</m:Qty>
</m:Item>
</m:Items>
</m:Order>
</m:CreateOrder>
</soap:Body>
5. Body 规则
# 必须存在且只有一个 # 命名空间必须正确 # 内容为业务数据或 Fault # 不能包含属性(除命名空间声明)
SOAP Fault 元素
SOAP Fault 元素
1. Fault 作用
# 当请求处理失败时,Body 中包含 Fault 元素 # 用于向发送方报告错误信息
2. Fault 结构(SOAP 1.2)
<soap:Body>
<soap:Fault>
<soap:Code>
<soap:Value>soap:Sender</soap:Value>
<soap:Subcode>
<soap:Value>m:InvalidItem</soap:Value>
</soap:Subcode>
</soap:Code>
<soap:Reason>
<soap:Text xml:lang="en">Invalid item name</soap:Text>
<soap:Text xml:lang="zh">无效的商品名称</soap:Text>
</soap:Reason>
<soap:Node>http://example.com/server</soap:Node>
<soap:Role>http://example.com/processor</soap:Role>
<soap:Detail>
<m:ErrorInfo xmlns:m="http://example.com">
<m:Code>E1001</m:Code>
</m:ErrorInfo>
</soap:Detail>
</soap:Fault>
</soap:Body>
3. Fault 结构(SOAP 1.1)
<soap:Fault>
<faultcode>soap:Client</faultcode>
<faultstring>无效的参数</faultstring>
<faultactor>http://example.com/server</faultactor>
<detail>
<m:Error xmlns:m="http://example.com">
详细信息
</m:Error>
</detail>
</soap:Fault>
4. 标准错误码
# SOAP 1.2 Code soap:VersionMismatch 版本不匹配 soap:MustUnderstand 必须理解的 header 未处理 soap:DataEncodingUnknown 数据编码未知 soap:Sender 发送方错误(参数错误) soap:Receiver 接收方错误(服务异常) # SOAP 1.1 faultcode soap:VersionMismatch soap:MustUnderstand soap:Client soap:Server
5. 处理 Fault
# 客户端解析错误
# Python(zeep)示例
from zeep import Client, Fault
client = Client("http://example.com/service?wsdl")
try:
result = client.service.GetPrice(Item="Invalid")
except Fault as e:
print("SOAP 错误:", e.message)
print("错误码:", e.code)
print("详情:", e.details)
SOAP HTTP Binding
SOAP HTTP Binding
1. HTTP 传输
# SOAP 最常用的传输方式 # 通过 HTTP POST 发送 XML 消息 # HTTP 请求头 POST /ws/service HTTP/1.1 Host: example.com Content-Type: application/soap+xml; charset=utf-8 Content-Length: 452
2. SOAP 1.2 请求示例
POST /ws/price HTTP/1.1
Host: example.com
Content-Type: application/soap+xml; charset=utf-8
Content-Length: 300
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:m="http://example.com/ws">
<soap:Body>
<m:GetPrice>
<m:Item>Apples</m:Item>
</m:GetPrice>
</soap:Body>
</soap:Envelope>
3. SOAP 1.1 请求示例
POST /ws/price HTTP/1.1
Host: example.com
Content-Type: text/xml; charset=utf-8
Content-Length: 300
SOAPAction: "http://example.com/ws/GetPrice"
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:m="http://example.com/ws">
<soap:Body>
<m:GetPrice>
<m:Item>Apples</m:Item>
</m:GetPrice>
</soap:Body>
</soap:Envelope>
4. 响应示例
HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset=utf-8
Content-Length: 250
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:m="http://example.com/ws">
<soap:Body>
<m:GetPriceResponse>
<m:Price>1.50</m:Price>
</m:GetPriceResponse>
</soap:Body>
</soap:Envelope>
5. HTTP 状态码
# 成功 200 OK 正常响应 # 错误 400 Bad Request 请求格式错误 404 Not Found 服务不存在 500 Internal Server Error 服务端错误 # 500 响应体通常包含 Fault # 内容类型 SOAP 1.2: application/soap+xml SOAP 1.1: text/xml + SOAPAction 头
SOAP 实例
SOAP 实例
1. 完整场景:天气预报服务
# 请求:查询城市天气
POST /weather HTTP/1.1
Host: api.example.com
Content-Type: application/soap+xml; charset=utf-8
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:w="http://example.com/weather">
<soap:Header>
<w:APIKey>KEY-12345</w:APIKey>
</soap:Header>
<soap:Body>
<w:GetWeather>
<w:City>北京</w:City>
<w:Days>3</w:Days>
</w:GetWeather>
</soap:Body>
</soap:Envelope>
# 响应
<soap:Envelope ...>
<soap:Body>
<w:GetWeatherResponse>
<w:Forecast>
<w:Date>2026-08-18</w:Date>
<w:Temperature>32°C</w:Temperature>
<w:Condition>晴</w:Condition>
</w:Forecast>
<w:Forecast>
<w:Date>2026-08-19</w:Date>
<w:Temperature>33°C</w:Temperature>
<w:Condition>多云</w:Condition>
</w:Forecast>
</w:GetWeatherResponse>
</soap:Body>
</soap:Envelope>
2. Python 调用 SOAP 服务
# 安装 zeep
# pip install zeep
from zeep import Client
# 根据 WSDL 创建客户端
client = Client("http://api.example.com/weather?wsdl")
# 调用服务(方法名来自 WSDL)
result = client.service.GetWeather(
City="北京",
Days=3
)
for forecast in result.Forecast:
print(f"{forecast.Date}: "
f"{forecast.Temperature}, {forecast.Condition}")
3. Java 调用 SOAP 服务
// 使用 JAX-WS 生成的客户端
WeatherService service = new WeatherService();
WeatherPort port = service.getWeatherPort();
// 设置认证 header
BindingProvider bp = (BindingProvider) port;
Map<String, Object> headers = new HashMap<>();
headers.put("APIKey", "KEY-12345");
bp.getRequestContext().putAll(headers);
// 调用
ForecastList result = port.getWeather("北京", 3);
for (Forecast f : result.getForecast()) {
System.out.println(f.getDate() + ": "
+ f.getTemperature());
}
SOAP 总结
SOAP 总结
1. 核心要点
- 消息结构:Envelope > Header + Body
- 命名空间:SOAP 1.1/1.2 命名空间不同
- 错误处理:Fault 元素报告错误
- 传输:通常基于 HTTP POST
- 契约:WSDL 描述接口
2. SOAP 的优点
- 标准化程度高,跨语言跨平台
- 强类型契约,接口清晰
- 安全标准成熟(WS-Security)
- 支持事务与可靠消息
3. SOAP 的缺点
- XML 消息冗长,带宽占用高
- 解析性能低
- 学习曲线陡峭
- 调试困难(消息复杂)
4. 何时选择 SOAP
- 企业级应用集成
- 金融/电信等对安全要求高的场景
- 已有 SOAP 基础设施的存量系统
- 需要事务、可靠消息等 WS-* 能力
5. 现代替代
REST + JSON 互联网 API 主流 gRPC 高性能 RPC GraphQL 灵活查询 Message Queue Kafka/RabbitMQ(异步) # 建议 # 新项目优先 REST/gRPC # 对接老系统时掌握 SOAP 基础即可
SOAP 学习指南
SOAP 学习指南
1. 学习路径
1. 理解 XML 基础与命名空间 2. 掌握 SOAP 消息结构(Envelope/Header/Body/Fault) 3. 熟悉 HTTP Binding(请求/响应格式) 4. 理解 WSDL 接口描述 5. 用客户端库实践(zeep/JAX-WS/SoapUI) 6. 了解 WS-Security 等扩展
2. 实践建议
- 用 SoapUI 调试 SOAP 服务(免费工具)
- 从公共 SOAP 服务练手(如天气、汇率)
- 对比 SOAP 与 REST 的请求差异
- 阅读 WSDL 理解服务契约
3. 调试工具
SoapUI SOAP 调试与测试(推荐) Postman 支持 SOAP 请求 Charles/Fiddler HTTP 抓包 Wireshark 底层报文分析
4. 常见问题
# Q: 命名空间错误? # A: 检查 Envelope 命名空间版本 # Q: Content-Type 错误? # A: 1.2 用 application/soap+xml, # 1.1 用 text/xml + SOAPAction # Q: 无法解析 WSDL? # A: 确认 WSDL URL 可访问,XSD 引用正确 # Q: 认证失败? # A: 检查 Header 中 Security/Token 配置
5. 资源推荐
W3C 规范: www.w3.org/TR/soap12 WSDL 规范: www.w3.org/TR/wsdl zeep 文档: docs.python-zeep.org SoapUI: www.soapui.org # 结语 # SOAP 虽老但仍在企业界广泛应用, # 理解其原理对系统集成和运维很重要。
第 1 / 11 节