一、WSDL简介
WSDL即为网络服务描述语言(Web Services Description Language),是一门基于 XML 的语言,用于描述 Web Services 以及如何对它们进行访问,一般用作不同语言的服务交互。
二、WSDL文件生成Java代码方式
以查找手机号归属地为例
1、找到WSDL文档
进入http://www.webxml.com.cn/zh_cn/web_services.aspx,找到国内手机号码归属地查询WEB服务的WSDL
2、导入WSDL并生成Java代码(推荐使用方式二)
方式一:项目中的某个包右键-->WebServices-->GenerateJavaCodeFromWsdl-->第一行url path将1中的网址拷入、键入包名-->Next生成java代码
方式二:使用JDK自带程序wsimport.exe导入wsdl文件
如下:E:\HI\test\src为导入的包的目录,com.mes.mobile为包名,http://之后为wsdl的地址
wsimport -keep -s E:\HI\test\src -p com.mes.mobile -verbose http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl
3、调用服务
public class JavaCodeMain {
public static void main(String[] args) {
MobileCodeWS service = new MobileCodeWS();
MobileCodeWSSoap port = service.getMobileCodeWSSoap();
String body = port.getMobileCodeInfo("15715700000",null);
System.out.println(body);
}
}
运行控制台输出:
15715700000:浙江 杭州 浙江移动全球通卡
4、优缺点
优点:不需要手写多少代码,方便快捷
缺点:WSDL文档不可控,有些WSDL文档生成代码会失败;生成的代码量较大,不方便阅读和修改
5、导入异常处理
(1)、报错undefined element declaration 's:schema',可能JAXB目前还不支持ref 这种元素的解析,目前普遍的解决办法是用<s:any minOccurs="2" maxOccurs="2"/>替代<s:element ref="s:schema"/><s:any />
(2)、使用JDK自带程序wsimport.exe导入wsdl文件可以在控制窗口看到详细报错信息,便于纠错
二、RPC方式
1、导入axis2依赖
<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-spring</artifactId>
<version>1.7.8</version>
</dependency>
<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-transport-http</artifactId>
<version>1.7.8</version>
</dependency>
<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-transport-local</artifactId>
<version>1.7.8</version>
</dependency>
<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-xmlbeans</artifactId>
<version>1.7.8</version>
</dependency>
2、RPC通过AXIS2调用webservice的通用方法
/**
* @description: RPC通过AXIS2调用webservice
* @params: serverUrl服务地址,methodName方法名,params参数,namespace命名空间,returnType返回类型
* @return: JSON
* @auther: WZH
* @date: 2019/8/6 9:31
*/
public static String getRPC(String serverUrl,String methodName,Object[] params,String namespace,Class[] returnType){
Object[] result = null;
try
{
RPCServiceClient client = new RPCServiceClient();
Options options = client.getOptions();
EndpointReference reference = new EndpointReference(serverUrl);
options.setTo(reference);
options.setAction(namespace+methodName);
QName qName = new QName(namespace, methodName);
result = client.invokeBlocking(qName, params, returnType);
System.out.println(Arrays.toString(result));
}
catch (AxisFault e)
{
e.printStackTrace();
}
return JSONObject.toJSONString(result);
}
3、主方法调用
String serverUrl = "http://www.webxml.com.cn/WebServices/WeatherWS.asmx?wsdl";
String methodName = "getWeather";
Object[] params = new Object[]{"重庆",""};
String namespace = "http://WebXml.com.cn/";
Class[] returnType = new Class[]{String.class};
String result = RemoteUtil.getRPC(serverUrl,methodName,params,namespace,returnType);
4、优缺点
优点:调用方便,代码简洁,数据不需要过多解析
缺点:容易出错,不易调通,目前传参时还未调通,仅不传参数时可使用
三、document方式
1、依赖同上
2、用document方式远程调用web服务
/**
* @description: 用document方式远程调用web服务
* @params: serverUrl服务地址,methodName方法名,params参数,namespace命名空间
* @return: String
* @auther: WZH
* @date: 2019/8/6 15:44
*/
public static String getDocument(String serverUrl,String methodName,String namespace,Map<String,Object> params) {
OMElement result = null;
try {
ServiceClient serviceClient = new ServiceClient();
EndpointReference reference = new EndpointReference(serverUrl);
Options options = serviceClient.getOptions();
options.setTo(reference);
//确定调用方法(wsdl 命名空间地址 (wsdl文档中的targetNamespace) 和 方法名称 的组合)
options.setAction(namespace+methodName);
OMFactory factory = OMAbstractFactory.getOMFactory();
OMNamespace space = factory.createOMNamespace(namespace, "");
OMElement method = factory.createOMElement(methodName, space);
// 指定方法的参数
if (params!=null){
params.forEach((key,value)->{
OMElement param = factory.createOMElement(key, space);
param.setText(value.toString());
method.addChild(param);
});
}
method.build();
//远程调用web服务
result = serviceClient.sendReceive(method);
} catch (AxisFault axisFault) {
axisFault.printStackTrace();
}
return JSONObject.toJSONString(result);
}
3、主方法调用
private static final String OM_ELEMENT = ">[^<]+<";
String serverUrl = "http://ws.webxml.com.cn/WebServices/WeatherWS.asmx";
String methodName = "getWeather";
String namespace = "http://WebXml.com.cn/";
Map<String,Object> params = new HashMap<>();
params.put("theCityCode","重庆");
params.put("theUserID","");
String result = RemoteUtil.getDocument(serverUrl,methodName,namespace,params);
//接收到为xml报文,自行根据实际情况做相应处理
Pattern pattern = Pattern.compile(OM_ELEMENT);
Matcher matcher = pattern.matcher(result);
List<String> list = new ArrayList<>();
while (matcher.find()){
String one = matcher.group(0);
list.add(one.replace(">","").replace("<",""));
System.out.println(matcher.group(0));
}
System.out.println(list);
4、优缺点
优点:稳定可靠,调用方便,代码简洁
缺点:接收到的数据为xml报文,需要自行根据实际情况做相应处理
四、HttpURLConnection方式
1、HttpURLConnection远程调用webservice的通用方法
/**
* @description: HttpURLConnection远程调用webservice的通用方法
* @params: url请求地址,method请求方式,soap请求体,property请求头
* @return: String
* @auther: WZH
* @date: 2019/8/7 10:53
*/
public static String httpConnection(String url,String method,String soap,Map<String,String> property) {
StringBuilder s = new StringBuilder();
try {
URL wsUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection) wsUrl.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestMethod(method);
if(property!=null){
property.forEach(conn::setRequestProperty);
}
conn.setConnectTimeout(2000);
conn.setReadTimeout(2000);
OutputStream os = conn.getOutputStream();
os.write(soap.getBytes());
InputStream is = conn.getInputStream();
byte[] b = new byte[1024];
int len;
while ((len = is.read(b)) != -1) {
String ss = new String(b, 0, len, "UTF-8");
s.append(ss);
}
is.close();
os.close();
conn.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
return s.toString();
}
2、主类的调用示例
String url = "http://www.webxml.com.cn/WebServices/MobileCodeWS.asmx";
String phoneNum = "15926662555";
Map<String,String> property = new HashMap<>(1);
property.put("Content-Type","text/xml;charset=UTF-8");
//构造soap请求体
String soap = "<?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><getMobileCodeInfo xmlns=\"http://WebXml.com.cn/\"><mobileCode>"+phoneNum+"</mobileCode><userID></userID></getMobileCodeInfo></soap:Body></soap:Envelope>";
//接收到为xml报文,自行根据实际情况做相应处理
String result = RemoteUtil.httpConnection(url,"POST",soap,property);
五、HttpClient方式
1、HttpClient远程调用webservice的通用方法(POST)
/**
* @description: HttpClient远程调用webservice的通用方法(POST)
* @params: url请求地址,soap请求报文,contentType内容类型
* @return: String
* @auther: WZH
* @date: 2019/8/7 13:54
*/
public static String httpClient(String url,String soap,String contentType){
HttpClient httpClient=new HttpClient();
PostMethod postMethod=new PostMethod(url);
String result = null;
try {
byte[] b=soap.getBytes("utf-8");
InputStream is = new ByteArrayInputStream(b, 0, b.length);
RequestEntity re = new InputStreamRequestEntity(is, b.length, contentType);
postMethod.setRequestEntity(re);
int statusCode = httpClient.executeMethod(postMethod);
if (statusCode==200){
result = postMethod.getResponseBodyAsString();
}
postMethod.releaseConnection();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
2、主类调用示例
String url = "http://www.webxml.com.cn/WebServices/MobileCodeWS.asmx";
String phoneNum = "15926662549";
//构造soap请求体
String soap = "<?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><getMobileCodeInfo xmlns=\"http://WebXml.com.cn/\"><mobileCode>"+phoneNum+"</mobileCode><userID></userID></getMobileCodeInfo></soap:Body></soap:Envelope>";
String contentType = "text/xml;charset=UTF-8";
//接收到为xml报文,自行根据实际情况做相应处理
String result = RemoteUtil.httpClient(url,soap,contentType);
以上方式总结
在WSDL文档质量有足够保证的情况下,优先采用方式一和二;
当可以获取请求和返回报文,数据相对方便解析时,可采用后三种备选方式。