★. WebService,顾名思义就是基于Web的服务。它使用Web(HTTP)方式,接收和响应外部系统的某种请求。从而实现远程调用.
我们可以调用互联网上查询天气信息Web服务,然后将它嵌入到我们的程序(C/S或B/S程序)当中来,当用户从我们的网点看到天气信息时,他会认为我们为他提供了很多的信息服务,但其实我们什么也没有做,只是简单调用了一下服务器上的一段代码而已。
学习WebService可以将你的服务(一段代码)发布到互联网上让别人去调用,也可以调用别人机器上发布的WebService,就像使用自己的代码一样.。
顾名思义:webservice是一个跨平台数据交互服务,不同的语言,不同的平台,只要读取我们webservice提供的数据,那么我们就会获取另一个平台的服务。
在学习Socket之前我们先来复习复习Socket:
★.Socket复习
- 什么是TCP/IP、UDP?
TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为广域网(WANs)设计的。
UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是属于TCP/IP协议族中的一种。
这里有一张图,表明了这些协议的关系。
抽象出Socket:
如下图:
Socket是什么呢?
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
你会使用它们吗?
前人已经给我们做了好多的事了,网络间的通信也就简单了许多,但毕竟还是有挺多工作要做的。以前听到Socket编程,觉得它是比较高深的编程知识,但是只要弄清Socket编程的工作原理,神秘的面纱也就揭开了。
一个生活中的场景。你要打电话给一个朋友,先拨号,朋友听到电话铃声后提起电话,这时你和你的朋友就建立起了连接,就可以讲话了。等交流结束,挂断电话结束此次交谈。 生活中的场景就解释了这工作原理,也许TCP/IP协议族就是诞生于生活中,这也不一定。
先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。
Webservice的几个名词:
- 名词1:XML. Extensible Markup Language -扩展性标记语言
- XML,用于传输格式化的数据,是Web服务的基础。
- namespace-命名空间。
- xmlns=“http://itcast.cn” 使用默认命名空间。
- xmlns:itcast=“http://itcast.cn”使用指定名称的命名空间。
- namespace-命名空间。
- XML,用于传输格式化的数据,是Web服务的基础。
- 名词2:WSDL – WebService Description Language – Web服务描述语言。
- 通过XML形式说明服务在什么地方-地址。
- 通过XML形式说明服务提供什么样的方法 – 如何调用。
- 名词3:SOAP-Simple Object Access Protocol(简单对象访问协议)
- SOAP作为一个基于XML语言的协议用于在网上传输数据。
- SOAP = 在HTTP的基础上+XML数据。
- SOAP是基于HTTP的。
- SOAP的组成如下:
- Envelope – 必须的部分。以XML的根元素出现。
- Headers – 可选的。
- Body – 必须的。在body部分,包含要执行的服务器的方法。和发送到服务器的数据。
- SOAP的组成如下:
- WebServer和Client的Socket通信
- 建立模拟服务端接收客户端数据的socket.
//模拟服务端
public class MyServer {
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(8809);
Socket socket = ss.accept();
InputStream inputStream = socket.getInputStream();
BufferedReader buff = new BufferedReader(new InputStreamReader(inputStream));
String str = buff.readLine();
System.out.println("客户端说:"+str);
buff.close();
ss.close(); }
}
- 建立模拟客户端发送数据
public class MyClient {
public static void main(String[] args) throws Exception {
Socket s = new Socket("192.168.2.133", 8809);
OutputStream out = s.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));
bw.write("我是中国人!我爱中国。");
bw.newLine();
bw.close();
s.close();
}
}
- 建立2个不同的server和client项目。
- 运行结果分析。
首先:先启动服务端,当socket.accept()后就阻塞,等待接收数据。
然后:启动客户端传送数据,服务端接收数据。
这时console就会接收到数据。但是为什么有些数据会接收不到呢?console空白。
我们采用debug,发现数据都被传递过来了,数据也被全部接收了,这时我们就发现原来这是程序运行超时,就是输出之前超时,没有输出。加上while(true)死循环一切ok.
当我们debug时,数据完整的输出了。输出如下所示:
客户端说:我是中国人!我爱中国。
ERROR: JDWP Unable to get JNI 1.2 environment, jvm->GetEnv() return code = -2JDWP exit error AGENT_ERROR_NO_JNI_ENV(183): [../../../src/share/back/util.c:820][h1]
- HTTP协议与SOAP协议
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
解析:http协议就是直接把数据放在请求体中,但是SOAP协议中:请求体的数据变成了xml格式,即他们唯一的区别在于:数据的封装形式发生了改变。
- 在浏览器访问服务端。
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
★.使用客户端调用手机号码服务
①.打开网址webxml.com.cn
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
②.使用jdk命令wsimport –s . url进行代码生成。
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
在dos界面执行命令:需要在你需要生成代码的目下进行执行:
例如:在D盘根目录下ws文件下执行:
首先:切换到ws目录下
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
然后:执行命令(如下图)
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
在ws下面生成代码如下:D:\ws\cn\com\webxml
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
③.把ws包下面的java代码复制到项目中。
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
④.模拟客户端手机号码服务
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
测试结果:
1333333:河北 秦皇岛 河北电信CDMA卡
★.查询天气预报
①.使用wsimport命令生成代码(同上)
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
②.浏览器页面另存为:保存xml文件进行修改,并改名为:a.xml
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消(注意:a.xml必须保存在这,不能删除,程序运行时需要检索xml文件)
执行成功,生成java代码及class代码:生成成功。
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
③.把代码考进web项目中进行模拟客户端访问
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
④.运行结果
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
- 删掉a.xml文件的解决方案
修改代码地址、从新指向网络地址:http://webservice.webxml.com.cn/WebServices/WeatherWS.asmx?wsdl
那么如何指向网络地址呢?
修改如下代码即可:我们的代码已经生成,所以我们重新指向网络地址获取实时预报信息
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
★.在java项目中发布第一个ws服务
在JDK1.6中JAX-WS规范定义了如何发布一个webService服务。
JAX-WS是指Java Api for XML – WebService
用Jdk1.6.0_21以后的版本发布一个WebService服务.
与Web服务相关的类,都位于javax.jws.*包中。
主要类有:
@WebService - 它是一个注解,用在类上指定将此类发布成一个ws.
Endpoint – 此类为端点服务类,它的方法publish用于将一个已经添加了@WebService注解对象绑定到一个地址的端口上。
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
- 创建一个发布程序
/**
* 发布一个webservice服务
* @author hubin
*webservice注解将java类标记为实现web service,或者将java接口标记为定义webservice接口
*/
@WebService
public class HelloService {
//注意:发布服务时,类里面必须有非静态的、非final的方法,这样才能发布。
/**
* 如果没有:class cn.itcast.server.HelloService does
* not contain any valid WebMethods. *
* 注意:我们发布,是需要类里面的方法被外部调用,所以类里面不允许
* 有静态方法和final方法,这样的方法不能被发布。
* @return
*/
public String sayHello(String name)
{
System.out.println("hello"+name);
return "hello";
}
public static void main(String[] args) {
String address = "http://192.168.2.121:8809/hello[h2] ";
HelloService helloService = new HelloService();
Endpoint.publish(address, helloService);
}
}
- 在客户端浏览器输入发布地址+?wsdl发布
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
生成xml文件如下:
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
- 发布webservice服务注意事项:
- 在类上添加@WebService注解。
- 这是jdk1.6提供的一个注解。它位于:javax.jws.*包中。
- 通过EndPoint(端点服务)发布一个webService。
- Endpoint也是jdk提供的一个专门用于发布服务的类,它的publish方法接收两个参数,一个是本地的服务地址,二是提供服务的类。它位于javax.xml.ws.*包中。
- static Endpoint.publish(String address, Object implementor)
在给定地址处针对指定的实现者对象创建并发布端点。 - stop方法用于停止服务。
- EndPoint发布完成服务以后,将会独立的线程运行。所以,publish之后的代码,可以正常执行。
- 其他注意事项:
- 给类添加上@WebService注解后,类中所有的非静态方法都将会对外公布。
- 不支持静态方法,final方法。-
- 如果希望某个方法(非static,非final)不对外公开,可以在方法上添加@WebMethod(exclude=true),阻止对外公开。
- 如果一个类上,被添加了@WebService注解,则必须此类至少有一个可以公开的方法,否则将会启动失败。
- .客户端调用webservice的第一种方式:通过wsimport命令解析wsdl生成客户端代码调用web服务。
- 在dos命令行执行命令生成java代码。
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
代码生成成功。
使用自定义包结构:
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
- 把代码考入我们项目下:
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
- 完成代码调用
调用之前先启动服务端:
public class App {
public static void main(String[] args) {
HelloServiceService hello = new HelloServiceService();
HelloService service[h3] = hello.getHelloServicePort();
String result = service.sayHello("我们都是中国人!");
System.out.println(result[h4] );
}
}
在服务端输出:System.out.println("hello"+name);
hello我们都是中国人!
解析:
首先调用服务端:
String address = "http://192.168.1.103:8809/hello";
HelloService helloService = new HelloService();
Endpoint.publish(address, helloService);
启动发布端,阻塞在发布这:等待客户端调用:
然后再运行:App
注意:一旦在浏览器发布后,生成了java代码,那么就不用管浏览器生成的xml代码,只需要启动服务端,发布等待客户端访问即可。
- WebService通过HTTP协议完成远程调用
- WebService只采用HTTP POST方式传输数据,不使用GET方式(get方式没有请求体,那么xml格式数据就无法发送);
但是:get请求方式的也可以,但是不在遵循soap协议,而是采用json格式的方式来访问。
-- 握手,WSDL-get,
-
- 普通http post的contentType为
- application/x-www-form-urlencoded
- WebService的contentType为-即在Http的基础上发SOAP协议
- text/xml 这是基于soap1.1协议。
- application/soap+xml 这是基于soap1.2协议。
- 普通http post的contentType为
- WebService从数据传输格式上作了限定。WebService所使用的数据均是基于XML格式的。目前标准的WebService在数据格式上主要采用SOAP协议。SOAP协议实际上就是一种基于XML编码规范的文本协议。
- SOAP – Simple Object Access protocol 简单对像访问协议。是运行在HTTP协议基础之上的协议。其实就是在HTTP协议是传输XML文件,就变成了SOAP协议。
- SOAP1.1和SOAP1.2的 namespace不一样。可以通过查看类
- javax.xml.ws.soap.SOAPBinding来查看里面的常量
- 默认情况下,Jdk1.6只支持soap1.1
- 即:@BindingType(value=javax.xml.ws.soap.SOAPBinding.SOAP11HTTP_BINDING)
第二种:使用原生的ajax调用web服务
- 由于使用ajax – js调用web服务完成不同于使用java代码调用。所以,必须要对SOAP文件非常的了解。
- 一般使用ajax调用,应该是在已经获知了以下信息以后才去调用:
- 获知请求(request)的soap文本。
- 获知响应(response)的soap文本。
请求文件和响应文本格式,一般会随web服务的发布一同发布。
我们可以通过WSExplorer获取上面两段文本。
Myeclipse集成了WSExplorer工具:
①.点击launch SOAP 图标
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
点击完毕打开如下浏览器:
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
②.点击WSDL page
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
③.启动helloService
public static void main(String[] args) {
String address = "http://192.168.1.103:8809/hello";
HelloService helloService = new HelloService();
Endpoint.publish(address, helloService);
}
④.把address复制到explorer里面执行
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
执行结果:
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
下面我们将会详细的看到SAOP请求体和返回体:
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
Ajax访问数据交互图:
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
Ajax原理分析:
发送一个请求后,客户端无法确定什么时候会完成这个请求,所以需要用事件机制来捕获请求的状态,XMLHttpRequest对象提供了onreadyStateChange事件实现这一功能。这类似于回调函数的做法。 onreadyStateChange事件可指定一个事件处理函数来处理XMLHttpRequest对象的执行结果,如:
ajaxObj=createAjaxObject(); var url="/MyTodoes/FetchText?id="+id; ajaxObj.open("Get",url,true); ajaxObj.onreadyStateChange=changeTabCallBack; ajaxObj.send(null); onreadyStateChange事件是在readyState属性发生改变时触发的,readyState的值表示了当前请求的状态,在事件处理程序中可以根据这个值来进行不同的处理。 readyState有五种可取值0:尚未初始化,1:正在加载,2:加载完毕,3:正在处理;4:处理完毕。一旦readyState属性的值变成了4,就可以从服务器返回的响应数据进行访问了。 通常在事件中判断readyState的值是在请求完毕时才做处理,如: function changeTabCallBack(){ if(ajaxObj.readyState==4){ // 下一步验证
} } Status存储了服务器端返回的Http请求响应代码,它表示请求的处理结果,常见响应代码的含义如右。 在Ajax开发中,最常用就是200这个响应码,代码如下: function changeTabCallBack(){ if(ajaxObj.readyState==4){ if(ajaxObj.status==200){ // 服务端返回了正确数据,开始响应处理 } } } Http状态码 含义 200 请求成功 202 请求被接受但处理未完成 400 错误请求 404 请求资源未找到 500 内部服务器错误
原生ajax代码解析:
//通过这个函数来异步获取信息
function Ajax(){
var xmlHttpReq = null; //声明一个空对象用来装入XMLHttpRequest
if (window.ActiveXObject){//IE5 IE6是以ActiveXObject的方式引入XMLHttpRequest的
xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
}
else if (window.XMLHttpRequest){//除IE5 IE6 以外的浏览器XMLHttpRequest是window的子对象
xmlHttpReq = new XMLHttpRequest();//实例化一个XMLHttpRequest
}
if(xmlHttpReq != null){ //如果对象实例化成功
xmlHttpReq.open("GET","test.jsp",true); //调用open()方法并采用异步方式
xmlHttpReq.onreadystatechange=RequestCallBack; //设置回调函数
xmlHttpReq.send(null); //因为使用get方式提交,所以可以使用null参调用
}
function RequestCallBack(){//一旦readyState值改变,将会调用这个函数
if(xmlHttpReq.readyState == 4){
if(xmlHttpReq.status == 200){
//将xmlHttpReq.responseText的值赋给ID为 resText 的元素
document.getElementById("resText").innerHTML = xmlHttpReq.responseText;
}
}
}
}
- AJAX运行步骤示义图
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
下面我们继续回归ajax访问:
我们需要SOAP Request Envelope作为我们的请求体:
<html>
<head>
<script type="text/javascript">
var xmlHttpRequest;
function ajax(){
//定义请求体
var requestBody[h5] ='<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/'+
'" xmlns:q0="http://server.itcast.cn/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" '+
'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'+
'<soapenv:Body><q0:sayHello><arg0>我是中国人</arg0></q0:sayHello> </soapenv:Body>'+
'</soapenv:Envelope>';
//1.创建ajax核心对象
xmlHttpRequest = new XMLHttpRequest();
//2,指定webservice的请求地址
var wsUrl = "http://192.168.24.30:8809/hello";
//3.打开连接
xmlHttpRequest.open("POST",wsUrl,true);
//4,重新设置请求头
xmlHttpRequest.setRequestHeader("Content-Type[h6] ","text/xml;charset=UTF-8");
//5.设置回调函数
xmlHttpRequest.onreadystatechange = _back;
//6.发送请求
xmlHttpRequest.send(requestBody);
alert(xmlHttpRequest);
}
function _back()
{
}
</script>
<body>
<input type="button" value="ajax提交Webservice" οnclick="ajax();" />
</body>
</head>
</html>
Ok,那么上面html异步请求代码搞定,我打开浏览器进行访问:
就会调用后台sayHello方法:并输出值:hello我是中国人
下面就开始执行:使用360浏览器
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
点击按钮发现后台console并没有值输出:而是如下警告错误:
五月 11, 2014 11:38:57 上午 com.sun.xml.internal.ws.transport.http.server.WSHttpHandler handleExchange
WARNING: Cannot handle HTTP method: OPTIONS
注意,使用ajax调用webservice时,尽量使用ie浏览器,如果使用chrome或者是firefox浏览器,会出现以下异常:2013-8-2517:02:30com.sun.xml.internal.ws.transport.http.server.WSHttpHandlerhandleExchange警告:CannothandleHTTPmethod:OPTIONSHTML
下面更换IE,果然好使:
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
输出结果:
hello我是中国人
点击一次输出一次:
√.添加返回函数
function _back()
{
if(xmlHttpRequest.readyState==4){
if(xmlHttpRequest.status==200)
{
alert("success");
}
}
}
再次访问:发现状态200,返回成功!输出success.
√.在请求里面放入页面输入的动态参数:
做法如下:
function ajax(){
//定义请求体
var requestBody='<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/'+
'" xmlns:q0="http://server.itcast.cn/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" '+
'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'+
'<soapenv:Body><q0:sayHello><arg0>'+document.getElementById('name').value+'[h7] </arg0></q0:sayHello> </soapenv:Body>'+
'</soapenv:Envelope>';
//1.创建ajax核心对象
xmlHttpRequest = new XMLHttpRequest();
//2,指定webservice的请求地址
var wsUrl = "http://192.168.24.30:8809[h8] /hello";
//3.打开连接
xmlHttpRequest.open("POST",wsUrl,true);
//4,重新设置请求头
xmlHttpRequest.setRequestHeader("Content-Type","text/xml;charset=UTF-8");
//5.设置回调函数
xmlHttpRequest.onreadystatechange = _back;
//6.发送请求
xmlHttpRequest.send(requestBody);
alert(xmlHttpRequest);
}
function _back()
{
if(xmlHttpRequest.readyState==4){
if(xmlHttpRequest.status==200)
{
var res = xmlHttpRequest.responseXML;
var ele = res.getElementsByTagName('return')[0];
alert(ele.textContent);
}
}
}
</script>
<body>
<input name="name" id="name[h9] " type="text"/><br/>
<input type="button" value="ajax提交Webservice" οnclick="ajax();" />
</body>
第三种:使用urlConnection方式来调用webservice服务。
①.第一步:启动服务端等待客户端数据
/**
* 发布一个webservice服务
* @author hubin
*webservice注解将java类标记为实现web service,或者将java接口标记为定义webservice接口
*/
@WebService
public class HelloService {
//注意:发布服务时,类里面必须有非静态的、非final的方法,这样才能发布。
/**
* 如果没有:class cn.itcast.server.HelloService does
* not contain any valid WebMethods. *
* 注意:我们发布,是需要类里面的方法被外部调用,所以类里面不允许
* 有静态方法和final方法,这样的方法不能被发布。
* @return
*/
public String sayHello(String name)
{
System.out.println("hello"+name);
return "hello " +name;
}
public static void main(String[] args) {
String address = "http://192.168.24.30:8809/hello";
HelloService helloService = new HelloService();
Endpoint.publish(address, helloService);
}
}
第二步:
编程urlConnection代码,然后发送请求体:
public class App {
public static void main(String[] args) throws Exception {
//指定服务请求地址
String url = "http://192.168.24.30:8809/hello";
String requestBody="<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/" +
"\" xmlns:q0=\"http://server.itcast.cn/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" "+
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"> "+
"<soapenv:Body><q0:sayHello><arg0>王后</arg0></q0:sayHello></soapenv:Body>"+
"</soapenv:Envelope>";
URL wsUrl = new URL(url);
HttpURLConnection connection = (HttpURLConnection) wsUrl.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("content-type", "text/xml;charset=utf-8");
//发送请求
OutputStream outputStream = connection.getOutputStream();
outputStream.write(requestBody.getBytes());
int code = connection.getResponseCode();
if(code==200)
{
//响应正常
//获取响应
InputStream inputStream = connection.getInputStream();
byte[] b = new byte[1024];
int len=0;
StringBuffer sb = new StringBuffer();
while((len=inputStream.read(b))!=-1)
{
String s = new String(b,0,len,"UTF-8");
sb.append(s);
}
System.out.println(sb.toString());
inputStream.close();
}
outputStream.close();
connection.disconnect();
}
}
第三步:运行urlconnection代码,发送请求;
结果如下:
服务端获取响应:
<?xml version="1.0" ?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><ns2:sayHelloResponse xmlns:ns2="http://server.itcast.cn/"><return>hello ????</return></ns2:sayHelloResponse></S:Body></S:Envelope>
客户端输出:
hello????
不识别中文,编码有误。
第四种:使用客户端编程的方式来访问服务端
①.使用wsimport –s . http://192.168.3.100/hello?wsdl命令生成代码
复制接口到使用目录下(只需要接口):
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
本例复制到:
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
编写客户端代码:
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
代码展示如下:
//使用客户端编程的方式
public class App {
public static void main(String[] args) throws Exception {
Service service = Service.create(new URL("http://192.168.24.30:8809/hello?wsdl"),
new QName("http://server.itcast.cn/", "HelloServiceService"));
HelloService port = service.getPort(new QName("http://server.itcast.cn/", "HelloServicePort"), HelloService.class);
String sayHello = port.sayHello("我是中国人");
System.out.println(sayHello);
}
}
运行结果:
首先启动服务端等待客户端数据、然后启动客户端传递参数:
客户端和服务端都同时输出:
hello 我是中国人
- 使用TCP/IP Monitor-拦截HTTP请求头和响应头及Body部分
此工具位于:window>show view>other>MyEclipse Common(常用工具)>TCP/IP Monitor
前面的WSExplorer只参获取 示例配置拦截本机到百度的请求:
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消消息体部分。为了获取HTTP
请求的具体信息,我们可以
使用monitor;
因为SOAP是在HTTP的
基础上发XML数据,前
面的XML数据已经可以
获取到了,那么,既然
是在HTTP上收发消息,
就一定会有HTTP的头信
息,那HTTP头信息又
是怎么样的呢?
使用工具步骤如下:
①.
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
②.
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
③.
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
④.
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
⑤.
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
⑥.
[h1]表示连接超时
[h2]启用该服务后,改程序将阻塞等待数据在客户端发布。
- 运行改程序
- 在浏览器输入这个地址+?wsdl,生成xml代码。Webservice服务生成成功。
- 使用端点服务,将对象
绑定到一个地址和端口。
同时必须要在端口后面
给服务取一个名称:hello或者任意一个
[h3]这是HelloService的代理对象。
[h4]Result结果为hello
因为我们在服务端:return“hello“,客户端收到返回结果。
[h5]requestBody里面的内容就是SOAP请求体里面的内容
[h7]插入下面html里面的动态参数。
[h8]本地通信IP
[h9]从这输入值,上面使用js代码获取值,把值放入Soap请求体,然后发送给服务端。服务端就可以接收到参数。
WebService开发指南
WebService针对软件开发和系统集成商提供移动商务的接入WebService具有稳定、跨平台、跨开发语言、穿透防火墙等特点因此深受企业开发亲睐。适应 WEB、VB 、Delphi、.NET、VC 、 JAVA 等多种主流开发语言及 Windows 、Linux 、Unix 等运行环境的短信通讯开发接口,让企业的 OA 、CRM 、ERP 、SCM 等系统快速、轻松实现移动商务应用。
适用于
1. CRM、ERP、OA、SCM软件系统
2. 网站 B2B、B2C类
3. 系统集成商
4. 中间件开发商
5. ……
典型应用:
●与Web嵌入 ● 与OA嵌入 ●与ERP嵌入 ● 与CRM嵌入● 软件开发商嵌入 ...
- 基本概况
|
|
- 调用方法
- 实例化对象(ASP.NET 示例)
- 第一步添加引用
Webservice地址: Service1 Web 服务
b.创建对象WebService.Service1 ws = new WebService.Service1();
- GetUserInfo
功能描述:读取用户账户信息。参数说明
输入参数 | 说明 | 类型 |
uid | 用户名 | String(6-10) |
pwd | 密码 | string(6-12) |
返回数据:
<?xml version="1.0" encoding="utf-8" ?>
<string xmlns="http://tempuri.org/">000/liugang123/310014.7000/0.1000/56/【世纪中正科技开发有限公司】/0.2000/0.3000/0.3000/winic/世纪中正科技开发有限公司/刘江/13580305095</string>
返回解释:
000/liugang123/310014.7000/0.1000/56/【世纪中正科技开发有限公司】/0.2000/0.3000/0.3000/winic/世纪中正科技开发有限公司/刘江/13580305095
000/用户名/余额/短信单价/短信字符数/签名/语音短信单价/传真单价/彩信单价/
所属经销商/公司名/联系人/联系方式
-03为帐号不存在或者密码错误
Asp.net示例
WebService.Service1 ws = new WebService.Service1();
txtResult.Text=ws.GetUserInfo(用户名, 密码);
- SendFax
功能描述:发送传真接口
参数说明
输入参数 | 说明 | 类型 |
uid | 用户名 | String(6-10) |
pwd | 密码 | string(6-12) |
faxno | 传真号码。区号加号码如 | String() |
men | 收件人。显示在传真纸上的,收件人(to) | string(1-4) |
title | 文档标题 显示在页眉上名称:如:报价单 | string(1-5) |
bytes | 传真数据流。 目前支持纯文本文件、RTF文件、WORD文档、EXCEL文档、POWER POINT文档、PDF文档、TIFF图片等。如果需要发送JPG、 GIF等其他格式的图片,请建立一个空的WORD文档,将图片插入到文档中再发送。 | base64Binary
(<2M) |
FileName | 文档名称(如:报价单.doc)注意:一定要带上扩展名 | string(1-20) |
otime | 定时发送 留空即时发送(目前不能定时发送) 格式是:20080819 09:10:00 | Datatime() |
返回一个信息编号(16位)
返回只要不是返回 “负数” (一串编号是成功)就是成功
<?xml version="1.0" encoding="utf-8" ?>
<string xmlns="http://tempuri.org/">0808191530315347</string>
Asp.net示例
WebService.Service1 ws = new WebService.Service1();
byte[] buffer = new byte[0];
if (fupFaxFilePath.FileName == "")
{
txtResult.Text="传真文件不能为空";
return;
}
else
{
FileStream fs = new FileStream(fupFaxFilePath.PostedFile.FileName, FileMode.Open); //Client Side Path
buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);
fs.Close();
}
string filename = fupFaxFilePath.PostedFile.FileName;
WebService.Service1 ws = new WebService.Service1();
try
{
this.txtResult.Text = ws.SendFax(txtUID.Text, txt_PWD.Text,txtFaxNO.Text, txtMen.Text,txtTitle.Text, buffer, filename);
}
catch
{
}
finally
{
// fs.Close();
}
- SendMessages
功能描述:发送短信接口
参数说明
输入参数 | 说明 | 类型 |
uid | 用户名 | String(6-10) |
pwd | 密码 | string(6-12) |
tos | 接收号码(小灵通区号加号码) 如:13909098887,13122321234 | string() 1-8000个号码 |
msg | 短信内容 60-70 字 | string(1-70) |
otime | 定时发送 留空即时发送 格式是:2008-08-19 09:10:00 | Datatime() |
返回一个信息编号(16位)
返回只要不是返回 “负数” (一串编号是成功)就是成功
<?xml version="1.0" encoding="utf-8" ?>
<string xmlns="http://tempuri.org/">0808191630319344</string>
Asp.net示例
WebService.Service1 ws = new WebService.Service1();
txtResult.Text = ws.SendMessages(用户名, 密码,手机号码, 短信内容, "");
- Sendvoice
功能描述:发送语音接口
参数说明
输入参数 | 说明 | 类型 |
Uid | 用户名 | String(6-10) |
Pwd | 密码 | string(6-12) |
Vno | 传真号码。区号加号码如 | String() |
Vtxt | 合成时需要的语音文字8000字以内 | string(5-8000) |
Mode | 类型(1=系统自动 2、人工合成、3文件) | string(1-5) |
FileBytes | *.WAV文件数据流。 | base64Binary
(<2M) |
Svrno | 客服座席电话。支持5路,用逗号分隔 | string(1-200) |
str_time | 定时发送 留空即时发送 格式是:20080819 09:10:00 | Datatime() |
end_time |
|
|
返回一个信息编号(16位)
<?xml version="1.0" encoding="utf-8" ?>
<string xmlns="http://tempuri.org/">0808191530315247</string>
Asp.net示例
WebService.Service1 ws = new WebService.Service1();
try
{
byte[] buffer;
if (RadioButtonList1.SelectedValue=="3")
{
string path = fupFvFilePath.FileName.ToString();
if (fupFvFilePath.FileName == "")
{
txtResult.Text="请选择语音文件。格式为.WAV 大小不要超过 2M";
return;
}
else
{
int i = fupFvFilePath.FileName.LastIndexOf(".");
//取得文档扩展名
string newext = fupFvFilePath.FileName.Substring(i+1).ToLower();
if (!newext.Equals("wav"))
{
txtResult.Text = "语音文件格式不正确";
return;
}
}
FileStream fs = new FileStream(fupFvFilePath.PostedFile.FileName, FileMode.Open);
buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);
fs.Close();
}
else
{
buffer = new byte[0];
}
WebService.Service1 ws = new WebService.Service1();
txtResult.Text = ws.SendVoice(txtUID.Text, this.txt_PWD.Text, this.txtFvTo.Text, this.txtFv.Text, RadioButtonList1.SelectedValue.ToString(), buffer, txtSvrNo.Text, "", "");
}
catch
{
txtResult.Text = "出错了";
}
finally
{
// fs.Close();
}
- TelCall
功能描述:网络电话
参数说明
输入参数 | 说明 | 类型 |
uid | 用户名 | String(6-10) |
pwd | 密码 | string(6-12) |
Host_call | 主叫电话号码 | String(10-13) |
caller | 被叫电话号码 | string(10-13) |
返回一个信息编号(16位) 返回只要不是 负数就是成功
<?xml version="1.0" encoding="utf-8" ?>
<string xmlns="http://tempuri.org/">0808191530315247</string>
Asp.net示例
WebService.Service1 ws = new WebService.Service1();
txtResult.Text=ws.TelCall(用户名, 密码,主叫号码,被叫号码);
- GetMessageRecord
功能描述:查询短信发送记录
参数说明
输入参数 | 说明 | 类型 |
uid | 用户名 | String(6-10) |
pwd | 密码 | string(6-12) |
num | 信息编号 | String(0-16) |
StartDate | 开始时间(目前无用,请留空) | dateTime |
endDate | 结束时间(目前无用,请留空) | dateTime |
isday | 查询记录的日期(只能查某一天,不能跨日期查询) | dateTime(20091109) |
注:1.num(编号)指短信发送成功之后返回的一个信息编号
2.编号与查询时间可以用空 根据你的须要查询
返回信息:(每条记录只能查询一次哦。查询之后记得保存哦)
<?xml version="1.0" encoding="utf-8" ?>
<string mlns="http://tempuri.org/">
test/0810271051368502/短信发成功/1/OK|test/1027135800228028/恭喜你。短信发送成功/1/OK|test/1029103706129604/世纪中正欢迎你/1/OK</string>
注:每条内容用反斜线(“/” )分隔,多条用单坚线(”|”)分隔
Test /0810271051368502/短信发成功/1 /OK
用户名 /信息编号 /短信内容 /短信条数 /发送状态
Asp.net示例
WebService.Service1 ws = new WebService.Service1();
txtResult.Text = ws. GetMessageRecord (用户名, 密码, 信息编码, 开始时间, 结束时间,查询日期);
- GetVoiceRecord
功能描述:查询语音发送记录
参数说明
输入参数 | 说明 | 类型 |
uid | 用户名 | String(6-10) |
pwd | 密码 | string(6-12) |
num | 信息编号 | String(0-16) |
StartDate | 开始时间 | dateTime |
endDate | 结束时间 | dateTime |
注:1.num(编号)指短信发送成功之后返回的一个信息编号
2.编号与查询时间可以用空 根据你的须要查询
返回信息:(每条记录只能查询一次哦。查询之后记得保存哦)
<?xml version="1.0" encoding="utf-8" ?>
<string mlns="http://tempuri.org/">
test/1025213426841244/008613480819361/79/0.4000/成功|test/1026203907748492/008613480819361/73/0.4000/成功|test/1026230337445969/008613480819361/0//0.0000/失败
</string>
注:每条内容用反斜线(“/” )分隔,多条用单坚线(”|”)分隔
Test /1025213426841244 /008613480819361 /79 /0.4000 /成功
用户名 /信息编号 /接收电话号码 /时长(秒)/费用 /发送状态
Asp.net示例
WebService.Service1 ws = new WebService.Service1();
txtResult.Text = ws.GetVoiceRecord(用户名, 密码, 信息编码, 开始时间, 结束时间);
- GetFaxRecord
功能描述:查询传真发送记录
参数说明
输入参数 | 说明 | 类型 |
uid | 用户名 | String(6-10) |
pwd | 密码 | string(6-12) |
num | 信息编号 | String(0-16) |
StartDate | 开始时间 | dateTime |
endDate | 结束时间 | dateTime |
注:1.num(编号)指短信发送成功之后返回的一个信息编号
2.编号与查询时间可以用空 根据你的须要查询
返回信息:(每条记录只能查询一次哦。查询之后记得保存哦)
<?xml version="1.0" encoding="utf-8" ?>
<string mlns="http://tempuri.org/">
test/0810171620343234/075525599862/5/0.3000/#101#对方挂机没给传真信号|
test/0810171620343234/075525599862/5/0.3000/#101#对方挂机没给传真信号|
test/0810171620343234/075525599862/5/0.3000/#101#对方挂机没给传真信号
zybtest/0911021135342556/#115/0/0.0000/
|zybtest/0911021138523114/#115/0/0.0000/
|zybtest/0911021145527470/075525599863/52/0.3000/成功|zybtest/0911051805131560/075525599863/67/0.6000/成功|zybtest/0911091612356823/075525599863/58/0.3000/成功
</string>
注:每条内容用反斜线(“/” )分隔,多条用单坚线(”|”)分隔
Test /0810171620343234/075525599862 /5 /0.3000/#101#对方挂机没给传真信号
用户名/信息编号 /接收传真电话号码/接收时长(秒) /费用 /发送状态
Asp.net示例
WebService.Service1 ws = new WebService.Service1();
txtResult.Text = ws.GetFaxRecord(用户名,密码, 编号, 开始时间, 结束时间);
- SendMMS
功能描述:发送彩信接口
参数说明
输入参数 | 说明 | 类型 |
uid | 用户名 | String(6-10) |
pwd | 密码 | string(6-12) |
mobno | 手机号码(只能是移动号码)。如 | String() |
title | 彩信标题 如:报价单 | string(1-5) |
content | 文字内容 | 500字 |
bytes | 图片数据流。目前支持JPG、GIF格式的图片 | base64Binary
(<50k) |
mmsFileName | 图片文件名(如:Honey.gif)注意:一定要带上扩展名 | string(1-20) |
返回一个信息编号(16位)
返回只要不是返回 “负数” (一串编号是成功)就是成功
<?xml version="1.0" encoding="utf-8" ?>
<string xmlns="http://tempuri.org/">0808191530315247</string>
Asp.net示例
WebService.Service1 ws = new WebService.Service1();
txtResult.Text=ws.SendMMS(用户名, 密码, 手机号码,彩信标题, 文字内容,图片数据流,图片文件名);
- GET_MSP_MO
功能描述:MSP接收短信
参数说明
输入参数 | 说明 | 类型 |
uid | 用户名 | String(6-10) |
pwd | 密码 | string(6-12) |
IDtype | (暂时留空) | string(6-12) |
返回一个信息编号(16位)
返回只要不是返回 “负数” (一串编号是成功)就是成功
<?xml version="1.0" encoding="utf-8" ?>
<string xmlns="http://tempuri.org/">0808191530315247</string>
Asp.net示例
WebService.Service1 ws = new WebService.Service1();
txtResult.Text=ws. GET_MSP_MO (用户名, 密码, “”);
- RegineUser
功能描述:注册用户
参数说明
输入参数 | 说明 | 类型 |
uid | 用户名 | String(6-10) |
pwd | 密码 | string(6-12) |
Agent_code | 经销商帐号 | String(6-50) |
co_name | 公司名称 | string(1-4) |
link_man | 联系人 | string(1-5) |
mob | 联系电话 | String(8-13) |
返回一个信息编号 如:000 成功
Asp.net示例
WebService.Service1 ws = new WebService.Service1();
txtResult.Text = ws. RegineUser(用户名,密码, 经销商帐号, 公司名称,联系人,联系电话);
- getMessageInfo
功能描述:得到短信处理状态报告
参数说明
输入参数 | 说明 | 类型 |
snum | 提交短信时返回的短信编号 | String(16) |
返回示例:
Null_OR_Waiting 无状态或者不存在此条短信
1/10531-自动/成功
处理批号/处理条数 经由哪个网关发送-处理方式/状态
1/1电信-等待处理/屏蔽字:咨询
处理批号/处理条数 经由哪个网关发送-状态/屏蔽字:***
- SMS_Reports
功能描述:得到短信发送状态报告(调用此接口是返回当天所有未查看的状态报告 如若返回-01 是因为你的余额<=10元)
注意:调用所得的数据有效性为一次 调用接口成功之后 数据当即改变状态为已查看,下次再调用接口 将不会再出现上次调用所返回的数据
参数说明
输入参数 | 说明 | 类型 |
uid | 用户名 | String(6-10) |
pwd | 密码 | string(6-12) |
返回示例:
null 暂时没有状态报告
0514181089386049/liugang123/13580305095/成功-10/2015-10-8 13:48:52/|0514181089386049/liugang123/13580305095/成功-10/2015-10-8 13:48:52/|
短信编号/帐号/手机号码/状态/时间|短信编号/帐号/手机号码/状态/时间|帐号/手机号码/状态/时间|
- GET_SMS_MO
功能描述:得到客户回复的信息
注意:调用所得的数据有效性为一次 调用接口成功之后 数据当即改变状态为已查看,下次再调用接口 将不会再出现上次调用所返回的数据
参数说明
输入参数 | 说明 | 类型 |
uid | 用户名 | String(6-10) |
pwd | 密码 | String(6-12) |
IDtype | 通道端口号(这个找业务人员设置) | String(3-5) |
返回示例:
null 暂时没有状态报告
13580305095/收到短信 谢谢/001/2015-10-8 12:06:56|13580305096/收到短信 谢谢/001/2015-10-8 12:06:56|
手机号码/回复内容/端口号/回复时间|手机号码/回复内容/端口号/回复时间|
- EditUserInfo
功能描述:修改客户个人信息
参数说明
输入参数 | 说明 | 类型 |
uid | 用户名 | String |
pwd | 密码 | String |
EntName | 公司名称(非空) | String |
linkMan | 联系人名称(非空) | String |
linkMobile | 手机号(非空) | String |
返回示例:
000为设置成功
其他为失败
- 常用返回状态说明
返回状态码 | 信息说明 |
0808191630319344(16位随机短信编号) | 成功! |
-01 | 当前账号余额不足! |
-02 | 当前用户ID错误! |
-03 | 当前密码错误! |
-04 | 参数不够或参数内容的类型错误! |
-05 | 手机号码格式不对!(目前还未实现) |
-06 | 短信内容编码不对!(目前还未实现) |
-07 | 短信内容含有敏感字符!(目前还未实现) |
null | 无接收数据 |
-09 | 系统维护中.. (目前还未实现) |
-10 | 手机号码数量超长! (目前还未实现) |
-11 | 短信内容超长!(70个字符)(目前不会返回-11,超长会分成多条发送) |
-12 | 其它错误! |
-13 | 文件传输错误 |