Bootstrap

Webservice

★. WebService,顾名思义就是基于Web的服务。它使用Web(HTTP)方式,接收和响应外部系统的某种请求。从而实现远程调用.

我们可以调用互联网上查询天气信息Web服务,然后将它嵌入到我们的程序(C/S或B/S程序)当中来,当用户从我们的网点看到天气信息时,他会认为我们为他提供了很多的信息服务,但其实我们什么也没有做,只是简单调用了一下服务器上的一段代码而已

学习WebService可以将你的服务(一段代码)发布到互联网上让别人去调用,也可以调用别人机器上发布的WebService,就像使用自己的代码一样.。

顾名思义:webservice是一个跨平台数据交互服务,不同的语言,不同的平台,只要读取我们webservice提供的数据,那么我们就会获取另一个平台的服务。

在学习Socket之前我们先来复习复习Socket:

★.Socket复习

  • 什么是TCP/IPUDP

         TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为广域网(WANs)设计的。
         UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是属于TCP/IP协议族中的一种。
        这里有一张图,表明了这些协议的关系。

 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQm9sdEJlYXI=,size_20,color_FFFFFF,t_70,g_se,x_16

 

抽象出Socket:

如下图:

 

 

Socket是什么呢?watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQm9sdEJlYXI=,size_18,color_FFFFFF,t_70,g_se,x_16
       Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
你会使用它们吗?
       前人已经给我们做了好多的事了,网络间的通信也就简单了许多,但毕竟还是有挺多工作要做的。以前听到Socket编程,觉得它是比较高深的编程知识,但是只要弄清Socket编程的工作原理,神秘的面纱也就揭开了。
       一个生活中的场景。你要打电话给一个朋友,先拨号,朋友听到电话铃声后提起电话,这时你和你的朋友就建立起了连接,就可以讲话了。等交流结束,挂断电话结束此次交谈。    生活中的场景就解释了这工作原理,也许TCP/IP协议族就是诞生于生活中,这也不一定。

 

 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQm9sdEJlYXI=,size_16,color_FFFFFF,t_70,g_se,x_16

 

先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。

  

Webservice的几个名词:

  1. 名词1:XML. Extensible Markup Language -扩展性标记语言
    • XML,用于传输格式化的数据,是Web服务的基础。
      • namespace-命名空间。
        • xmlns=“http://itcast.cn” 使用默认命名空间。
        • xmlns:itcast=“http://itcast.cn”使用指定名称的命名空间。
  2. 名词2:WSDL – WebService Description Language – Web服务描述语言。
    • 通过XML形式说明服务在什么地方-地址。
    • 通过XML形式说明服务提供什么样的方法 – 如何调用。
  3. 名词3:SOAP-Simple Object Access Protocol(简单对象访问协议)
    • SOAP作为一个基于XML语言的协议用于在网上传输数据。
    • SOAP = 在HTTP的基础上+XML数据。
    • SOAP是基于HTTP的。
      • SOAP的组成如下:
        • Envelope – 必须的部分。以XML的根元素出现。
        • Headers – 可选的。
        • Body – 必须的。在body部分,包含要执行的服务器的方法。和发送到服务器的数据。
  • 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协议

 

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

解析:http协议就是直接把数据放在请求体中,但是SOAP协议中:请求体的数据变成了xml格式,即他们唯一的区别在于:数据的封装形式发生了改变。

  • 在浏览器访问服务端。

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

★.使用客户端调用手机号码服务

①.打开网址webxml.com.cn

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

②.使用jdk命令wsimport –s . url进行代码生成。

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

在dos界面执行命令:需要在你需要生成代码的目下进行执行:

例如:在D盘根目录下ws文件下执行:

首先:切换到ws目录下

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

然后:执行命令(如下图)

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

在ws下面生成代码如下:D:\ws\cn\com\webxml

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

③.把ws包下面的java代码复制到项目中。

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

④.模拟客户端手机号码服务

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

测试结果:

1333333:河北 秦皇岛 河北电信CDMA

.查询天气预报

①.使用wsimport命令生成代码(同上)

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

②.浏览器页面另存为:保存xml文件进行修改,并改名为:a.xml

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消(注意:a.xml必须保存在这,不能删除,程序运行时需要检索xml文件)

执行成功,生成java代码及class代码:生成成功。

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

③.把代码考进web项目中进行模拟客户端访问

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

④.运行结果

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

  • 删掉a.xml文件的解决方案

修改代码地址、从新指向网络地址:http://webservice.webxml.com.cn/WebServices/WeatherWS.asmx?wsdl

那么如何指向网络地址呢?

修改如下代码即可:我们的代码已经生成,所以我们重新指向网络地址获取实时预报信息

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

★.在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注解对象绑定到一个地址的端口上。

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

  • 创建一个发布程序

/**

 * 发布一个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发布

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

生成xml文件如下:

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

  • 发布webservice服务注意事项:
  1. 在类上添加@WebService注解。
    • 这是jdk1.6提供的一个注解。它位于:javax.jws.*包中。
  2. 通过EndPoint(端点服务)发布一个webService。
    • Endpoint也是jdk提供的一个专门用于发布服务的类,它的publish方法接收两个参数,一个是本地的服务地址,二是提供服务的类。它位于javax.xml.ws.*包中。
    • static Endpoint.publish(String address, Object implementor)
                在给定地址处针对指定的实现者对象创建并发布端点。
    • stop方法用于停止服务。
    • EndPoint发布完成服务以后,将会独立的线程运行。所以,publish之后的代码,可以正常执行。
  3. 其他注意事项:
    • 给类添加上@WebService注解后,类中所有的非静态方法都将会对外公布。
    • 不支持静态方法,final方法。-
    • 如果希望某个方法(非static,非final)不对外公开,可以在方法上添加@WebMethod(exclude=true),阻止对外公开。
    • 如果一个类上,被添加了@WebService注解,则必须此类至少有一个可以公开的方法,否则将会启动失败。
  • .客户端调用webservice的第一种方式:通过wsimport命令解析wsdl生成客户端代码调用web服务。
  • 在dos命令行执行命令生成java代码。

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

代码生成成功。

使用自定义包结构:

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

  • 把代码考入我们项目下:

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

  • 完成代码调用

调用之前先启动服务端:

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协议完成远程调用
  1. 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协议。

 

  1. WebService从数据传输格式上作了限定。WebService所使用的数据均是基于XML格式的。目前标准的WebService在数据格式上主要采用SOAP协议。SOAP协议实际上就是一种基于XML编码规范的文本协议。

 

  1. SOAP – Simple Object Access protocol 简单对像访问协议。是运行在HTTP协议基础之上的协议。其实就是在HTTP协议是传输XML文件,就变成了SOAP协议。

 

  1. 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服务

  1. 由于使用ajax – js调用web服务完成不同于使用java代码调用。所以,必须要对SOAP文件非常的了解。
  2. 一般使用ajax调用,应该是在已经获知了以下信息以后才去调用:
    • 获知请求(request)的soap文本。
    • 获知响应(response)的soap文本。

请求文件和响应文本格式,一般会随web服务的发布一同发布。

我们可以通过WSExplorer获取上面两段文本。

Myeclipse集成了WSExplorer工具:

①.点击launch SOAP 图标

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

点击完毕打开如下浏览器:

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

②.点击WSDL page

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

③.启动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里面执行

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

执行结果:

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

下面我们将会详细的看到SAOP请求体和返回体:

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

Ajax访问数据交互图:

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

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运行步骤示义图

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

 

 

 

 

 

 

 

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

下面我们继续回归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浏览器

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

点击按钮发现后台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,果然好使:

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

输出结果:

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命令生成代码

复制接口到使用目录下(只需要接口):

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

本例复制到:

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

编写客户端代码:

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

代码展示如下:

 

//使用客户端编程的方式

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只参获取                      示例配置拦截本机到百度的请求:

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消消息体部分。为了获取HTTP

请求的具体信息,我们可以

使用monitor;

因为SOAP是在HTTP

基础上发XML数据,前

面的XML数据已经可以

获取到了,那么,既然

是在HTTP上收发消息,

就一定会有HTTP的头信

息,那HTTP头信息又

是怎么样的呢?

使用工具步骤如下:

①.

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

 

②.

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

③.

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

④.

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

⑤.

uploading.4e448015.gif正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消

⑥.


 [h1]表示连接超时

 [h2]启用该服务后,改程序将阻塞等待数据在客户端发布。

  1. 运行改程序
  2. 在浏览器输入这个地址+?wsdl,生成xml代码。Webservice服务生成成功。
  3. 使用端点服务,将对象

绑定到一个地址和端口。

同时必须要在端口后面

给服务取一个名称:hello或者任意一个

 

 [h3]这是HelloService的代理对象。

 [h4]Result结果为hello

因为我们在服务端:return“hello“,客户端收到返回结果。

 [h5]requestBody里面的内容就是SOAP请求体里面的内容

 [h6]注意:

这里大小写的问题:

Content,Type首字母大写。

 [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嵌入● 软件开发商嵌入 ...

 

  • 基本概况

 

Webservice地址:  Service1 Web 服务

uploading.4e448015.gif正在上传…重新上传取消

 

 

 

 

 

 

 

 
  • 调用方法

 

  1. 实例化对象(ASP.NET 示例)
  1. 第一步添加引用

Webservice地址:  Service1 Web 服务

b.创建对象WebService.Service1 ws = new WebService.Service1();

  1. 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(用户名, 密码);

  1. SendFax

功能描述:发送传真接口

参数说明

输入参数

说明

类型

uid

用户名

String(6-10)

pwd

密码

string(6-12)

faxno

传真号码。区号加号码如
(075525500998,075525599833,075525511223)

String()
多个用 ,号分隔每次提交1000个

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();

        }

 

  1. 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(用户名, 密码,手机号码, 短信内容, "");

 

  1. Sendvoice

功能描述:发送语音接口

参数说明

输入参数

说明

类型

Uid

用户名

String(6-10)

Pwd

密码

string(6-12)

Vno

传真号码。区号加号码如
(075525500998,075525599833,075525511223)

String()
多个用 ,号分隔每次提交1000个

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();

        }

 

  1. 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(用户名, 密码,主叫号码,被叫号码);

 

 

 

  1. 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 (用户名, 密码, 信息编码, 开始时间, 结束时间,查询日期);

 

  1. 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(用户名, 密码, 信息编码, 开始时间, 结束时间);

 

  1. 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(用户名,密码, 编号, 开始时间, 结束时间);

  1. SendMMS

功能描述:发送彩信接口

参数说明

输入参数

说明

类型

uid

用户名

String(6-10)

pwd

密码

string(6-12)

mobno

手机号码(只能是移动号码)。如
(13411112222,13577778888,13966665555)

String()
多个用 ,号分隔每次提交1000个

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(用户名, 密码, 手机号码,彩信标题, 文字内容,图片数据流,图片文件名);

  1. 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 (用户名, 密码, “”);

  1. 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(用户名,密码, 经销商帐号, 公司名称,联系人,联系电话);

 

  1. getMessageInfo

功能描述:得到短信处理状态报告

参数说明

输入参数

说明

类型

snum

提交短信时返回的短信编号

String(16)

返回示例:

Null_OR_Waiting 无状态或者不存在此条短信

 

1/10531-自动/成功

处理批号/处理条数 经由哪个网关发送-处理方式/状态

 

1/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/|

 

短信编号/帐号/手机号码/状态/时间|短信编号/帐号/手机号码/状态/时间|帐号/手机号码/状态/时间|

 

  1. 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|

手机号码/回复内容/端口号/回复时间|手机号码/回复内容/端口号/回复时间|

 

 

  1. 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

文件传输错误

 

 

 

 

;