WebService能够使运行在不同机器上的不同应用无需借助附加的、专门的第三方软件或引荐,就可相互交换数据或集成。依据WebService的规范实施的应用之间,无论它们所使用的语言、平台或内部协议是什么,都可以相互交换数据。
WebService就是一个部署在web服务器上的应用程序,它向外界暴露出一个能够通过web进行调用的API。这就是说,能用编程的方法通过web来调用这个应用程序。我们把调用这个WebService的应用程序称为客户端,发布这个web服务的机器称为WebService服务器。
架构趋势(WebService架构):
现在项目可能存在多种类型的终端,例如ipad等终端可能只有页面,需要远程调用控制层或业务逻辑。
一、调用已发布的WebService服务
接下来就以查询手机号码归属地为例,看看程序是如何调用WebService服务。
在开始写代码之前,首先需要添加HttpClient依赖,HttpClient是一款测试工具,可以在java代码中模拟HTTP请求协议。
maven依赖:
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
登录http://www.webxml.com.cn在最新web services中找到国内手机号码归属地查询WEB服务:
点击进入如下页面:
点击getMobileCodeInfo可以看到有SOAP1.1、SOAP1.2、HTTP GET、HTTP POST四种请求方式,接下来先看看HTTP GET请求。
1.1 get请求
上面一段表示发送请求数据格式、下面一段表示返回的数据格式。
代码清单:
/**
* 调用第三方ws服务,查询手机号码归属地
*
*/
public class PhoneClient {
public static void main(String[] args) throws IOException {
String number = "13888888888";
get(number);
}
public static void get(String number) throws IOException {
// 创建浏览器对象
HttpClient httpClient = new HttpClient();
String url = "http://ws.webxml.com.cn" +
"/WebServices/MobileCodeWS.asmx/getMobileCodeInfo?mobileCode="+ number +"&userID=";
// 填写数据,发送请求
GetMethod getMethod = new GetMethod(url);
int code = httpClient.executeMethod(getMethod);
System.out.println("http状态:" + code);
String result = getMethod.getResponseBodyAsString();
System.out.println("返回结果为:" + result);
}
}
【测试结果】:
http状态:200
返回结果为:<?xml version="1.0" encoding="utf-8"?>
<string xmlns="http://WebXml.com.cn/">13888888888:云南 昆明 云南移动合家欢卡</string>
1.2 post请求
同样地,上面的部分表示请求的数据格式和响应,下面的部分表示返回数据
代码清单:
/**
* 调用第三方ws服务,查询手机号码归属地
*
*/
public class PhoneClient {
public static void main(String[] args) throws IOException {
String number = "13888888888";
post(number);
}
public static void post(String number) throws IOException {
// 创建浏览器对象
HttpClient httpClient = new HttpClient();
String url = "http://ws.webxml.com.cn" +
"/WebServices/MobileCodeWS.asmx/getMobileCodeInfo";
// 填写数据,发送请求
PostMethod postMethod = new PostMethod(url);
postMethod.setParameter("mobileCode", number);
postMethod.setParameter("userID", "");
int code = httpClient.executeMethod(postMethod);
System.out.println("http状态:" + code);
String result = postMethod.getResponseBodyAsString();
System.out.println("返回结果为:" + result);
}
}
【测试结果】:
http状态:200
返回结果为:<?xml version="1.0" encoding="utf-8"?>
<string xmlns="http://WebXml.com.cn/">13888888888:云南 昆明 云南移动合家欢卡</string>
上面的两种方式本质上依然是http请求。
1.3 soap方式调用WebService
soap即简单对象访问协议。
从上图中发现用的依然是http post方法,但是请求的数据格式变成了XML,有利于数据的维护。
我们使用流的方式读取请求的数据格式,在resources文件下添加soap.txt文件:
<?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>13888888888</mobileCode>
<userID></userID>
</getMobileCodeInfo>
</soap:Body>
</soap:Envelope>
代码清单:
/**
* 调用第三方ws服务,查询手机号码归属地
*
*/
public class PhoneClient {
public static void main(String[] args) throws Exception {
soap();
}
public static void soap() throws IOException {
// 创建浏览器对象
HttpClient httpClient = new HttpClient();
String url = "http://ws.webxml.com.cn" +
"/WebServices/MobileCodeWS.asmx";
PostMethod postMethod = new PostMethod(url);
// 传输XML数据,通过流的方式加载xml数据
String filepath = "D:\\IDEASpace\\WebService-Sample\\MyClient\\src\\main\\resources\\soap.txt";
postMethod.setRequestBody(new FileInputStream(filepath));
int code = httpClient.executeMethod(postMethod);
System.out.println("http状态:" + code);
String result = postMethod.getResponseBodyAsString();
System.out.println("返回结果为:" + result);
}
}
【测试结果】:
这是因为post请求格式默认为:
Content-Type: application/x-www-form-urlencoded
当使用soap是需要指定:
Content-Type: text/xml; charset=utf-8
那么,手动设置一下Content-Type的值,添加一行代码:
postMethod.setRequestHeader("Content-Type", "text/xml;charset=utf-8");
二、使用wsimport生成客户端代码并调用ws服务
通过HttpClient工具模拟http请求在java bean调用ws服务获取手机查询功能。调用的方式:get/post/soap。本质上还是通过http方式调用,只是调用的时候可以传输XML数据。HttpClient是java调用http协议的解决方案,这就有了语言瓶颈,只能限于java语言。
WebService推荐的解决方案:wsimport命令
接下来,打开jdk的安装目录,在bin下可以看到这样一个命令:
这个就是java的ws解决方案。
首先,在号码归属地页面找到服务说明。点击进入获取的它网址:
http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?WSDL
1.命令:
wsimport http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?WSDL
解析WSDL(WS描述语言),解析完成后生成Java Bean
2.命令:
wsimport -s . http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?WSDL
解析完成后生成class和java源文件
3.命令:
wsimport -s . -p com.xxyh.webservice http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?WSDL
解析完成后生成class和java源文件,及自定义包结构:
接着,将java源文件添加进项目:
我们在com.xxyh.webservice包下创建一个PhotoMain类:
public class PhoneMain {
public static void main(String[] args) {
// 获取一个ws服务
MobileCodeWS ws = new MobileCodeWS();
// 获取具体的服务类型get post soap1.1 soap1.2
MobileCodeWSSoap wsSoap = ws.getMobileCodeWSSoap();
String address = wsSoap.getMobileCodeInfo("13888888888", null);
System.out.println("手机归属地信息为:" + address);
}
}
【测试结果】:
手机归属地信息为:13888888888:云南 昆明 云南移动合家欢卡