已整理成完整项目,并进行了优化。看参考地址:
https://gitee.com/andy_longjie/soap-call-service
SOAP的作用:
客户端:取得服务端的服务描述文件WSDL,解析该文件的内容,了解服务端的服务信息,以及调用方式。根据需要,生成恰当的SOAP请求消息(指定调用的方法,已经调用的参数),发往服务端。等待服务端返回的SOAP回应消息,解析得到返回值。
服务端:生成服务描述文件,以供客户端获取。接收客户端发来的SOAP请求消息,解析其中的方法调用和参数格式。根据WSDL和WSML的描述,调用相应的COM对象来完成指定功能,并把返回值放入SOAP回应消息返回给用户。
下面以“天气预报”为例 (http://www.webxml.com.cn/WebServices/WeatherWebService.asmx ),自己封装几个类,做一个接口访问。
封装SOAP访问参数的实体类:SoapParam.java
package andy.demo.tests;
/**
*
* @文件名 :SoapParam.java<br>
* @类描述 :调用 webservice的配置类<br>
* @作者 :Andy.wang<br>
* @创建时间 :2013-11-7下午2:45:36<br>
* @更改人 :<br>
* @更改时间 :<br>
*/
public class SoapParam {
/**
* 多个参数名或多个参数值,之间的分隔符
*/
public static final String SPLITFLAG = "!";
/**
* 空构造,属性初始化
*/
public SoapParam() {
// TODO Auto-generated constructor stub
super();
this.url = "";
this.methodName = "";
this.interfaceName = "";
this.paraNames = "";
this.paraValues = "";
}
/**
* 构造,属性赋值
*
* @param url
* @param methodName
* @param interfaceName
* @param paraNames
* @param paraValues
*/
public SoapParam(String url, String methodName, String interfaceName,
String paraNames, String paraValues) {
this.url = url;
this.methodName = methodName;
this.interfaceName = interfaceName;
this.paraNames = paraNames;
this.paraValues = paraValues;
}
/**
* webservice 发布的URL地址
*/
private String url;
/**
* 要调用的方法名
*/
private String methodName;
/**
* 要调用方法的接口名
*/
private String interfaceName;
/**
* 要调用方法的参数名,(有多个参数用”#“号隔开;没有参数可不写)。
*/
private String paraNames;
/**
* 要调用方法的参数值,(同多个参数值用”#“号隔开;没有的话就不写)必须与参数名的个数一致。
*/
private String paraValues;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
public String getInterfaceName() {
return interfaceName;
}
public void setInterfaceName(String interfaceName) {
this.interfaceName = interfaceName;
}
public String getParaNames() {
return paraNames;
}
public void setParaNames(String paraNames) {
this.paraNames = paraNames;
}
public String getParaValues() {
return paraValues;
}
public void setParaValues(String paraValues) {
this.paraValues = paraValues;
}
}
获取WebService 返回结果的类:GetResult.java (提供两种结果,一种为字符串,一种为InputStream流)
package andy.demo.tests;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
/**
*
* @文件名 :GetResult.java<br>
* @类描述 :获取服务器端返回的结果<br>
* @作者 :Andy.wang<br>
* @创建时间 :2013-11-7下午3:00:46<br>
* @更改人 :<br>
* @更改时间 :<br>
*/
public class GetResult {
// SoapRequeatContent 的 错误返回码
private final String faultCode = "-1";
private SoapParam soapParam;
/**
* 构造,给属性soapParam赋值
*
* @param soapParam
*/
public GetResult(SoapParam soapParam) {
// TODO Auto-generated constructor stub
this.soapParam = soapParam;
}
/**
*
* 方法名 :getSoapRequestContent<br>
* 方法描述 :获取请求的Soap内容<br>
* 创建者 :Andy.wang<br>
* 创建时间 :2013-11-7下午3:03:41 <br>
*
* <a href="\"http://www.eoeandroid.com/home.php?mod=space&uid=7300\"" target="\"_blank\"">@return</a> 返回类型 :String
*/
private String getSoapRequestContent() {
StringBuffer sb = new StringBuffer(16);
// 头部分
sb.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+ "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
+ "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" "
+ "xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"
+ "<soap:Body>");
// 中间部分
String methodName = soapParam.getMethodName();
String interfaceName = soapParam.getInterfaceName();
String paraNames = soapParam.getParaNames();
String paraValues = soapParam.getParaValues();
if (null == methodName || "".equals(methodName)
|| null == interfaceName || "".equals(interfaceName)) {
return faultCode;
}
sb.append("<" + methodName.trim() + " xmlns=\"" + interfaceName.trim()
+ "\">");
if (null != paraNames && null != paraValues) {
String names[] = paraNames.split(SoapParam.SPLITFLAG);
String values[] = paraValues.split(SoapParam.SPLITFLAG);
// 参数名的个数 必须和 实参的个数一致
if (names.length == values.length) {
for (int i = 0; i < names.length; i++) {
if (!names<i>.trim().equals("")) {
// 参数为:1级数组
sb.append("<" + names<i>.trim() + ">"
+ values<i>.trim() + "</" + names<i>.trim()
+ ">");
}
}
}
}
sb.append("</" + methodName.trim() + ">");
// 尾部分
sb.append("</soap:Body></soap:Envelope>");
return sb.toString();
}
public InputStream getResponseForInputStream() {
String soap = getSoapRequestContent();
return getResponseForInputStream(soap);
}
public String getResponseForString() {
String soap = getSoapRequestContent();
return getResponseForString(soap);
}
/**
*
* 方法名 :getResponseForInputStream<br>
* 方法描述 :获取服务器响应返回的流<br>
* 创建者 :Andy.wang<br>
* 创建时间 :2013-11-7下午3:31:39 <br>
*
* @return 返回类型 :InputStream
*/
private InputStream getResponseForInputStream(String soap) {
System.out.println(soap);
// 获取请求的soap内容错误
if (soap.equals(faultCode)) {
return null;
}
URL url = null;
InputStream is = null;
try {
url = new URL(soapParam.getUrl());
URLConnection conn = url.openConnection();
conn.setUseCaches(false);// POST请求 禁用缓存
conn.setReadTimeout(6000);// 设置请求时间
conn.setDoInput(true);// 设置从conn读入
conn.setDoOutput(true);// 设置从conn输出
conn.setRequestProperty("Content-Length",
Integer.toString(soap.length()));
conn.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
conn.setRequestProperty(
"SOAPAction",
String.valueOf(soapParam.getInterfaceName()
+ soapParam.getMethodName()));
OutputStream os = conn.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
osw.write(soap);
osw.flush();
osw.close();
is = conn.getInputStream();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return is;
}
/**
*
* 方法名 :getResponseForString<br>
* 方法描述 :获取服务器响应返回的字符串<br>
* 创建者 :Andy.wang<br>
* 创建时间 :2013-11-7下午3:57:19 <br>
*
* @param is
* :服务器响应返回的流
* @return
* @throws IOException
* 返回类型 :String
*/
private String getResponseForString(String soap) {
try {
InputStream is = getResponseForInputStream(soap);
if (null == is) {
return null;
}
ByteArrayOutputStream os = new ByteArrayOutputStream();
byte[] buffer = new byte[1024 * 100];
int len = 0;
while ((len = is.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
buffer = os.toByteArray();
os.flush();
os.close();
is.close();
return os.toString("UTF-8");
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return null;
}
}
测试类:Test.java
输出结果:
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><getSupportProvince xmlns="http://WebXml.com.cn/"></getSupportProvince></soap:Body></soap:Envelope>
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><getSupportProvinceResponse xmlns="http://WebXml.com.cn/"><getSupportProvinceResult>< string>直辖市</string><string>特别行政区< /string><string>黑龙江</string><string>吉林< /string><string>辽宁</string><string>内蒙古< /string><string>河北</string><string>河南< /string><string>山东</string><string>山西< /string><string>江苏</string><string>安徽< /string><string>陕西</string><string>宁夏< /string><string>甘肃</string><string>青海< /string><string>湖北</string><string>湖南< /string><string>浙江</string><string>江西< /string><string>福建</string><string>贵州< /string><string>四川</string><string>广东< /string><string>广西</string><string>云南< /string><string>海南</string><string>新疆< /string><string>西藏</string><string>台湾< /string><string>亚洲</string><string>欧洲< /string><string>非洲</string><string>北美洲< /string><string>南美洲</string><string>大洋洲< /string></getSupportProvinceResult></getSupportProvinceResponse></soap:Body></soap:Envelope>
已整理成完整项目,并进行了优化。看参考地址: