HttpUrlConnection 发送 SOAP 请求,SAX 解析 SOAP 响应
并附上抓包工具:wireshark
并附上抓包工具:wireshark
/*
* Socket远程调用Web服务实现,并用SAX解析XML文件,适用于性能要求较高场合
*/
package com.mypack.soap.client;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Stack;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
/**
* 为了提高WebService调用效率,因此手Socket自已实现,无需依赖任何Soap引擎
* @version 1.0
* @date 2010-08-21
*/
public final class SoapClientAsHttpUrlConnection
{
/**
* apache 日志记录器,底层可切换实现
*/
private static Log logger = LogFactory.getLog(SoapClientAsHttpUrlConnection.class);
/**
* 为了简单直接写了,最好单独写一方法并采用 Executors 启动线程,将返回值加入 BlockingQueue
*/
public static void main(String[] args) throws URISyntaxException, IOException, SAXException
{
// soap request string
final String soapReuqest = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><soapenv:Body><ns1:queryUser soapenv:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:ns1=\"http://services.zhang.com\"><in0 xsi:type=\"ns2:UserInfo\" xsi:nil=\"true\" xmlns:ns2=\"http://tdo.zhang.com\"/></ns1:queryUser></soapenv:Body></soapenv:Envelope>";
// Web 服务所在的地址
URI uri = new URI("http://10.40.51.156:28888/testSoap/services/UserManage");
URL url = uri.toURL();
// 打开连接
HttpURLConnection httpUrlConnection = (HttpURLConnection) url.openConnection();
// 可读取
httpUrlConnection.setDoInput(true);
httpUrlConnection.setDoOutput(true);
httpUrlConnection.setRequestMethod("POST");
// set request header
httpUrlConnection.setRequestProperty("SOAPAction", "");
//httpUrlConnection.setRequestProperty("Content-Length", soapReuqest.length() + "");
OutputStream os = httpUrlConnection.getOutputStream();
PrintWriter out = new PrintWriter(os);
out.println(soapReuqest);
out.flush();
StringBuilder sb = new StringBuilder();
// http status ok
if (HttpURLConnection.HTTP_OK == httpUrlConnection.getResponseCode())
{
if (logger.isDebugEnabled())
{
logger.debug("HTTP_OK");
}
InputStream is = httpUrlConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
for (String line = br.readLine(); line != null; line = br.readLine())
{
sb.append(line);
}
is.close();
}
// Release resource
os.close();
out.close();
httpUrlConnection.disconnect();
String soapResponse = sb.toString();
System.out.println(soapResponse);
// parse the soap response
// 底层是xces解析器,效率较高
XMLReader xmlReader = XMLReaderFactory.createXMLReader();
SimpleHandler handler = new SimpleHandler();
xmlReader.setContentHandler(handler);
InputSource inputSource = new InputSource(new StringReader(soapResponse));
try
{
xmlReader.parse(inputSource);
}
catch (ExtSAXException e)
{
}
// 便于演示,直接打出,生产环境请匆如此使用,可用日志进行 debug
System.out.println("Response is " + handler.response);
}
/**
* SAX 处理器,底层运用观察者模式
* 对于XML这种结构,运用栈进行存储
* 如果解析到目标串,利用抛出自定义异常来提前终止操作,提高效率
*/
private static class SimpleHandler extends DefaultHandler
{
/**
* 用栈缓存上下文信息
*/
private final Stack<String> stack = new Stack<String>();
private String response;
/**
* 每次传递 16K 数据,这一点很重要,但是在这里只需要一个串,因此忽略
*/
@Override
public void characters(char[] ch, int start, int length)
throws SAXException
{
if (!stack.empty() && "queryUserReturn".equals(stack.pop()))
{
response = new String(ch, start, length);
// 抛出异常,结束解析
throw new ExtSAXException();
}
}
/**
* 元素开始自动触发,将开始标签压栈缓存
*/
@Override
public void startElement(String uri, String localName, String name,
Attributes atts) throws SAXException
{
if ("queryUserReturn".equals(localName))
{
stack.push(localName);
}
}
}
/**
* 自定义异常,用于终止解析任务
*/
private static class ExtSAXException extends SAXException
{
private static final long serialVersionUID = 1L;
}
}