调用w3school.com的SOAP服务失败,遇两种异常求助
问题分析与解决办法
嘿,咱们来拆解一下你遇到的两个SOAP服务调用问题,以及对应的解决思路:
1. 核心问题:收到HTML而非SOAP响应
你碰到的XmlPullParserException是最关键的信号——服务返回的是<html>页面,完全不是预期的<soap:Envelope>格式响应。这大概率不是代码的锅,而是以下几种情况:
- w3school的旧SOAP服务已经下线或地址变更,现在访问原来的端点会直接跳转到官网页面;
- 请求的URL写错了,指向了w3school的普通网页而非SOAP接口的专属端点;
- HTTP请求头配置不全,比如没加
Content-Type: text/xml; charset=utf-8或SOAPAction头,导致服务根本识别不出这是SOAP请求。
2. 先验证SOAP服务是否还能用
建议先用Postman或者curl手动发个SOAP请求测试一下端点:
比如针对之前的CurrencyConverter服务,正确的请求格式应该是这样的:
<?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <ConversionRate xmlns="http://www.webserviceX.NET/"> <FromCurrency>USD</FromCurrency> <ToCurrency>EUR</ToCurrency> </ConversionRate> </soap:Body> </soap:Envelope>
如果发送后返回的还是HTML,那这个服务肯定是用不了了,建议换个更稳定的测试SOAP服务,比如经典的.NET计算器服务,端点地址是www.dneonline.com/calculator.asmx。
3. 解决「Stream Closed」异常的思路
第一次遇到的流关闭异常,通常是这几个原因导致的:
- HTTP连接超时设置太短,响应还没读完就断开了;
- 代码里错误地提前关闭了输入流或者Transport连接;
- 服务端因为请求格式不对,主动断开了连接。
4. 具体修复步骤
- 更换可用的测试服务:用刚才说的计算器服务,它的SOAP格式清晰,长期稳定;
- 完善请求配置:确保设置正确的请求头和合理的超时时间,示例代码如下:
// 初始化KeepAliveTransport,设置10秒的连接和读取超时 KeepAliveHttpsTransportSE transport = new KeepAliveHttpsTransportSE("www.dneonline.com", 443, "/calculator.asmx", 10000, 10000); // 配置必要的SOAP请求头 List<Header> headers = new ArrayList<>(); headers.add(new Header("Content-Type", "text/xml; charset=utf-8")); headers.add(new Header("SOAPAction", "\"http://tempuri.org/Add\"")); transport.setHeaders(headers); // 构造加法请求的SOAP消息 SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); envelope.dotNet = true; // 适配.NET编写的服务 SoapObject request = new SoapObject("http://tempuri.org/", "Add"); request.addProperty("intA", 10); request.addProperty("intB", 20); envelope.setOutputSoapObject(request); // 发送请求并处理响应 try { transport.call(null, envelope); SoapPrimitive response = (SoapPrimitive) envelope.getResponse(); System.out.println("计算结果:" + response.toString()); } catch (Exception e) { e.printStackTrace(); // 打印服务返回的完整错误内容,方便排查问题 if (transport.getErrorStream() != null) { String errorContent = new BufferedReader( new InputStreamReader(transport.getErrorStream()) ).lines().collect(Collectors.joining("\n")); System.out.println("服务返回的错误内容:\n" + errorContent); } }
- 添加错误日志:捕获异常时打印服务返回的完整内容,这能帮你快速判断是请求写错了,还是服务本身不可用。
内容的提问来源于stack exchange,提问作者Margerite
相关产品推荐
相关产品推荐

