Webservice异步系统

来源:互联网 发布:软件ui界面设计 编辑:程序博客网 时间:2024/06/14 06:43

Webservice 基础概念

1.类似天气预报数据 , 就是气象局对外提供的公共服务 .

2.Webservice 就是 异步系统的数据交互 , 数据调用 是跨语言的 , 跨平台的, 如 : java / c# / c++ / php / 手机终端/ 等 , 原因就是它们之间实际使用 xml 的数据格式进行交互 . json也可以

3.Webservice : 2端的一个概念 : 服务提供端(生产者) 和 调用服务者(消费者) . 如 : 银行, 也不是想象的那么庞大 , 就一个核心系统(钱的存取), 然后又很多的外围系统 (网银系统 / atm系统等) , 外围系统最终都要与核心进行交互 , 这时就用到了 webservice .

4.WebService是 SOA (面向服务架构 ) 实现方案

(将软件业务做成服务, 在进行服务 定制整合 )

5.企业内部经常用 web service 进行分布式系统 整合 (crm客户管理 与 业务 bos 与 财务系统的调用)

6.Webservice 基于 http协议 , http底层基于 socket 协议

7.webservice的基础就是socket式的服务端 和 客户端的数据交换 , 输入流 和 输出流,最底层的处理 , 后面的具体使用 , 都做了封装处理

8.如果涉及到 2 端的交互 , 就会有相关的协议规范 .

9. 概念

l  soa : 面向服务框架

l  xml : extensible markup language 扩展标记语言

u  namespace-命名空间。(域名/项目名称/服务名)

u  xmlns=“http://itcast.cn” 使用默认命名空间。

u  xmlns:itcast=“http://itcast.cn”使用指定名称的命名空间

l  wsdl : webservice descriptionlanguage

非常重要 , 就是调用者 ,要看的 , 买东西 , 去使用看说明书

l  soap : simple object access protocol  文本协议

基于 xml 语言的协议,其实是做了严格的规范 ,不能自定义 ; http基础上 + xml数据 ,特有的http协议 ,同样有请求响应;

特殊于 http 的地方 :

contentType : text/xml ; charset=utf-8

格式 :有严格的规范

Envelope (包层)–必须的部分。以XML的根元素出现。

Headers – 可选的。

Body – 必须的。在body部分,包含要执行的服务器的方法。和发送到服务器的数据。

 

 

基础 socket实例

Socket 代码  , webservice就是基于此实现 , 不过已经做了封装 ,webservice的应用写不到这类底层的代码了

服务端 socket

public class MyServer {

 

      public static void main(String[] args) throws Exception {

           ServerSocket ss = new ServerSocket(7788);

           //死循环

           while(true){

               //阻塞

                 Socket s = ss.accept();

                 InputStream inputStream = s.getInputStream();

                

                 BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));

                 String readLine = br.readLine();

                 System.out.println("客户端说:"+ readLine);

                 br.close();

                 s.close();

           }

      }

}

客户端 socket

public class MyClient {

      public static void main(String[] args) throws UnknownHostException, IOException {

           Socket s = new Socket("192.168.1.100",7788);

          

           OutputStream outputStream = s.getOutputStream();

           BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(outputStream));

           bw.write("你好,吃了吗?");

           bw.close();

           s.close();

      }

}

用完流一定要关闭 , 输出流关闭会默认执行flush()刷出

 

网络服务 – wsdl文档应用案例

网站 : www.webxml.com.cn webservice 相关很多的免费服务 诸如 : 航班 / 天气预报 / 手机号归属地 / 电子邮件地址验证 / ip地址来源等

网站 : www.ele.me 饿了么外餐派送网站 , 就有通过 ip 查询你的地址

 

Jdk内置命令 : java / javac / doc

还有 : wsimport 对wsdl 介绍文档 , 解析生成 java 代码(java文件 和 .class 字节码文件) ; 生成命令 : wsimport –s[指定生成jave文件存放目录] –p[包名] url(wsdl文档完整url地址名,  : http://www.itcast.server.cn/sayHello?wsdl)

 

网络服务 – www.webxml.com.cn 免费服务

直接url地址解析生成 , 就ok

 

Wsimport –s . –pcn.itcast.server.teleSearch http://webservice.webxml.com.cn/WebServices/WeatherWS.asmx?wsdl

解析后 报错(网络服务经常会用的事) ,  是有 未定义的元素 , ‘s :schema’ 15行 / 61行

/ 101行 , 解决办法 , 把此网页 保存下载 , 自定义名称 为 : teleSearch.xml

(可选,可保存默认提供名称) , 删除上面保存几行的代码 ,  执行 :

 

l   Wsimport –s . –p cn.itcast.server.teleSearchteleSearch.xml (注意在当下目录下进行)

l   解析生成 java文件 , 删除 .class 文件(用作 tomcat运行用) , 我们这里做测试 , 只需把 java文件拷到工程包下 ,进行实现 .如下 java 文件

l   实现完成 ,是否可以删除 teleSearch.xml文件 ?

不行 ,服务已经依赖这个文件

解决修改 WeatherWs.java类中 [@WebServiceClient的属性wsdlLocation = ‘值设为网络url地址’]

调用服务代码

自定义开发 webservice-jdk提供实现

那么如何才可以发布一个WebService呢?

在JDK1.6中JAX-WS规范定义了如何发布一个webService服务。

    JAX-WS是指Java Api for XML – WebService.

1.用Jdk1.6.0_21以后的版本发布一个WebService服务.

2.与Web服务相关的类,都位于javax.jws.*包中。

主要类有:

1      @WebService - 它是一个注解,用在类上指定将此类发布成一个ws. Endpoint – 此类为端点服务类,它的方法publish用于将一个已经添加了@WebService注解对象绑定到一个地址的端口上。

2步实现发布

l  1、在类上添加@WebService注解。

•  这是jdk1.6提供的一个注解。它位于:javax.jws.*包中。

l  2、通过EndPoint(端点服务)发布一个webService。

•  Endpoint也是jdk提供的一个专门用于发布服务的类,它的publish方法接收两个参数,一个是本地的服务地址,二是提供服务的类。它位于javax.xml.ws.*包中。

•  static Endpoint.publish(String address, Object implementor)
          在给定地址处针对指定的实现者对象创建并发布端点。

•  stop方法用于停止服务。

•  EndPoint发布完成服务以后,将会独立的线程运行。所以,publish之后的代码,可以正常执行。

l  其他注意事项:

•  给类添加上@WebService注解后,类中所有的非静态方法都将会对外公布。

•  @WebService注解,作用在具体类上。而不是接口

•  不支持静态方法,final方法。因为 代理机制处理,final无法继承使用-

•  如果希望某个方法(非static,非final)不对外公开,可以在方法上添加@WebMethod(exclude=true),阻止对外公开。

•  如果一个类上,被添加了@WebService注解,则必须此类至少有一个可以公开的方法,否则将会启动失败。

 

 

注解的作用

l  通过WebService的注解,可以更加形像的描述Web服务。从而生成WSDL文档。

l  当修改了WebService注解之后,同时会影响客户端生成的代码。

l  调用的方法名和参数名也发生了变化。

l  即使是没有修改源代码,只修改了注解,客户端的代码也必须要重新生成(注意是生成而不是下载)。否则调用将会失败。

l  生成本地调用代码,依然使用wsimport工具。

l  WebMethod  / WebParam  / WebResult  / WebService

WebService参数

 

@WebMethod参数

 

@WebResult用于定制返回值到WSDL的映射:

@WebParam用于定义WSDL中的参数映射:

注意: main方法不提供调用

代码示例 及 4种客户端调用服务

服务端提供服务

/**

 * WebService注解将 Java类标记为实现 Web Service,或者将 Java接口标记为定义 Web Service接口。

 */

 

@WebService(serviceName="HelloService",targetNamespace="http://www.itcast.cn")

public class HelloService {

      @WebMethod(operationName="sayHi") //注解自定义方法名称

      @WebResult(name="myReturn") //注解自定义返回写法名称

      public String sayHello(

                 @WebParam(name="name") //自定义生成wsdl的属性名

                 String name,

                 @WebParam(name="age") //自定义生成wsdl的属性名

                 Integer age){

           System.out.println("sayHello()...");

           return "hello " + name;

      }

     

      @WebMethod(exclude=true) //实现外部不提供调用 ,内部可以继续使用

      public String sayHi(String name){

           System.out.println("sayHello()...");

           return "hello " + name;

      }

      public static void main(String[] args) {

           //参数1:服务的发布地址参数2:服务的提供者(实现着)

                // 新开一个线程去处理

           Endpoint.publish("http://192.168.1.100:6789/hello", new HelloService());

                 //会打印出来 ,和上面的publish不冲突,不同的线程(main)

           System.out.println("server ready...");

      }

}

客户端调用服务

1种方式通过wsimport生成客户端代码(简单易用,本地代码使用)

 

public static void main(String[] args) {

           /*

            * WSDL:

            * <service name="HelloServiceService">

            * <port name="HelloServicePort" binding="tns:HelloServicePortBinding">

            */

       //直接 new提供服务的服务 (环环相套)

           HelloServiceService hss = new HelloServiceService();

      //获取绑定端口 ,就可以使用绑定的服务  - 方法 

           HelloService hs = hss.getHelloServicePort();

           String str = hs.sayHello("lisi");

           System.out.println(str);

           System.out.println(hs.getClass().getSimpleName());

      }

2种方式通过客户端编程的方式调用(依赖一个接口)

出现原因 : 因为第 1 , 代码量很多 , 伴随依赖 ,这里减少了依赖 ,只需服务接口

public static void main(String[] args) throws Exception {

           Service s = Service.create

(new URL("http://192.168.1.100:6789/hello?wsdl"),  //通过 2 个参数 url

new QName("http://ws.itcast.cn/","HelloServiceService")); //qname(名称空间 /服务名称)  // getport依然是代理对象

           HelloService port = s.getPort

//QName表示 XML规范中定义的限定名称

(new QName("http://ws.itcast.cn/","HelloServicePort"),  HelloService.class);

           String sayHello = port.sayHello("王五", 23);

           System.out.println(sayHello);

             //查看字节码文件名称 ,旨在查看是否为代理对象

           System.out.println(port.getClass().getName());

      }

3种方式通过ajax调用js+XML(跨域,浏览器不支持) 

 

Ajax 原始实现

<head>

           <title>使用ajax调用WS</title>

           <script>

           //下面的案例没有使用jquery , 而是使用原始的底层 ajax - xmlHttpRequest 实现

                 var xhr ;//xmlHttpRequest

                 function sendAjax(){

                      //适用于 ie 1.6 的创建 , 直接new , 没做处理

                      //xhr = new ActiveXObject("Microsoft.XMLHTTP");

                      xhr = ajaxFunction();

 

                      //指定服务的请求地址

                      var wsUrl = "http://192.168.1.100:9876/hi";

                     

                      //构造请求体

                      var requestBody =   '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"'+

                                                  ' xmlns:q0="http://ws.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+'</arg0><arg1>10</arg1> </q0:sayHello>' +

                                                  ' </soapenv:Body></soapenv:Envelope>';

 

                            requestBody = '<?xml version="1.0" ?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><ns2:sayHi xmlns:ns2="http://cxf.itcast.cn/"><arg0>jack</arg0></ns2:sayHi></S:Body></S:Envelope>';

 

                      //打开连接

                      xhr.open("POST",wsUrl,true);

 

                      //重新设置请求头

                      xhr.setRequestHeader("Content-Type","text/xml;charset=UTF-8");

 

                      //设置回调函数

                      xhr.onreadystatechange = _back;

 

                      //发送请求

                      xhr.send(requestBody);

                 }

 

                 //定义回调函数

                 function _back(){

                      if(xhr.readyState == 4){

                            if(xhr.status == 200){

                                  var ret = xhr.responseXML;

                                  var ele = ret.getElementsByTagName("return")[0];

                                  //alert(ele.text);

                                  document.getElementById("showInfo").innerHTML = ele.text;

                            }

                      }

                 }

      //创建XMLHttpRequest对象:

      function ajaxFunction(){

         var xmlHttp;

         try{ // Firefox, Opera 8.0+, Safari

           xmlHttp=new XMLHttpRequest();

          }

          catch (e){

              try{// Internet Explorer

                  xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");

                 }

               catch (e){

                 try{

                  xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");

                 }

                 catch (e){}

                 }

          }

     

           return xmlHttp;

       }

 

           </script>

      </head>

      <body>

           <input type="text" id="name">

           <input type="button" value="使用ajax调用WS" onclick="sendAjax();">

           <div id="showInfo"></div>

      </body>

4中方式 URLconnection调用 ws(其实和 ajax一样 )

 

public class ClientApp {

      public static void main(String[] args) throws Exception {

           // 指定服务的请求地址

           URL wsUrl = new URL("http://192.168.1.100:6789/hello");

 

           // 打开连接并强转

           URLConnection openConnection = wsUrl.openConnection();

 

           HttpURLConnection httpConnection = (HttpURLConnection) openConnection;

 

           // 设置

           httpConnection.setDoInput(true); //打开输入

           httpConnection.setDoOutput(true); //打开输出

           httpConnection.setRequestMethod("POST"); //请求方式

           httpConnection.setRequestProperty("Content-Type",

                      "text/xml;charset=UTF-8"); //头设置

 

           // 构造请求体中间通过了转译处理 /

           String requestBody = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\""

                      + " xmlns:q0=\"http://ws.itcast.cn/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""

                      + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"

                      + "<soapenv:Body><q0:sayHello> <arg0>jack</arg0><arg1>10</arg1> </q0:sayHello></soapenv:Body></soapenv:Envelope>";

 

           // 向服务端写入数据

           OutputStream outputStream = httpConnection.getOutputStream();

           outputStream.write(requestBody.getBytes());

 

           int responseCode = httpConnection.getResponseCode();

 

           if (responseCode == 200) {

                 // 从服务端读取数据

                 InputStream inputStream = httpConnection.getInputStream();

                 byte[] b = new byte[1024];

                 int len = 0;

                 StringBuffer sb = new StringBuffer();

                         //读取知道完 ,完就返回 -1 ,停止

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

           httpConnection.disconnect();

      }

 

Wsdl 描述文件详解

概念

l  wsdl – WebService Description Language(WS描述语言)

l  它主要定义了三个方面的问题:

•  What?即服务是什么?

• (portType,types,message)

•  How?如何调用服务?

• 通过binding元素说明调用服务的方式:soap,soap12,post,get.

•  Where?在哪儿调用服务?

• Service元素,soap:address.

代码 - 从下往上进行读解

<?xml version="1.0"encoding="UTF8" ?>

//定义的soap 1.1的命名空间

<definitions xmlns:soap=http://schemas.xmlsoap.org/wsdl/soap/

//web服务的命名空间 ,默认是倒转的包名 ,可自定义

      xmlns:tns="http://ws.itcast.cn/"xmlns:xsd="http://www.w3.org/2001/XMLSchema"

      xmlns="http://schemas.xmlsoap.org/wsdl/"targetNamespace="http://ws.itcast.cn/"

      name="HelloServiceService"> //定义的服务名

      <types> //no.1定义一组参数类型 ,即方法所接受的参数,通过另一个xml 实现

           <xsd:schema>

                 <xsd:importnamespace=http://ws.itcast.cn/

      //通过此 xml实现对应 : no.1

                      schemaLocation="http://localhost:9999/hello?xsd=1"/>

           </xsd:schema>

      </types>

      <messagename="sayHi">

           <partname="parameters" element="tns:sayHi" />

      </message>

      <messagename="sayHiResponse">

           <partname="parameters" element="tns:sayHiResponse" />

      </message>

      //定义服务接口

      <portTypename="HelloService">

      //提供的方法操作方法-可调用的方法

           <operationname="sayHi">

                 <inputmessage="tns:sayHi" />

                 <outputmessage="tns:sayHiResponse" />

           </operation>

      </portType>

      //对应下面的绑定类型 , service服务绑定提供服务类

      <bindingname="HelloServicePortBinding" type="tns:HelloService">

           <soap:bindingtransport="http://schemas.xmlsoap.org/soap/http"

                 style="document"/>

           <operationname="sayHi">

                 <soap:operationsoapAction="" />

                 <input>

                      <soap:bodyuse="literal" />

                 </input>

                 <output>

                      <soap:bodyuse="literal" />

                 </output>

           </operation>

      </binding>

      //服务名称 提供服务类名 +service

      <servicename="HelloServiceService">

      //端口绑定

           <portname="HelloServicePort"binding="tns:HelloServicePortBinding">

      //访问服务地址   定义服务类型 : soap / soap12 / get / post

                 <soap:addresslocation="http://localhost:9999/hello" />

           </port>

      </service>

</definitions>

 

WebService通过HTTP协议完成远程调用

l  WebService只采用HTTP POST方式传输数据,不使用GET方式; get 方式 – 做握手,WSDL-get,(get的请求体有长度显示 , 不能完成 有格式要求的数据传输)

•  普通http post的contentType为

• application/x-www-form-urlencoded

•  WebService的contentType为-即在Http的基础上发SOAP协议

• text/xml 这是基于soap1.1协议。

• application/soap+xml 这是基于soap1.2协议。

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

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

SOAP请求过程分析:

l  第一步:使用get方式获取wsdl文件,称为握手。

•  对于JDK1.6生成的ws服务,由于内部有一两个配置文件,所以会发出两次get请求。

•  其他的一般为一次。

l  第二步:用户发出请求将使用post方式。

l  第三步:服务器响应成功。

获取wsdl文件-握手的请求与响应:tcp/ip monitor

同时发出 2 个请求 , 1 get 建立握手wsdl ; 2 post 调用服务

以下是拦截到的请求/响应信息:

发出去的XML文本:

<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>    //SOAP协议必须拥有body元素

    <q0:sayHello>    //SOAP协议必须通过第一个节点指明需要调用的方法

      <arg0>aaa</arg0>

    </q0:sayHello>

  </soapenv:Body>

</soapenv:Envelope>

 

第二行:http://schemas.xmlsoap.org/soap/envelope/soap1.1schema

拦截到的返回信息:

<?xml version="1.0" ?>

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">

    <S:Body>

       <ns2:sayHiResponse xmlns:ns2="http://ws.itcast.cn/">

           <return>HelloWorld</return>

      </ns2:sayHiResponse>

   </S:Body>

</S:Envelope>

 

虽然修改了前缀,但用的是同一个命名空间。

SOAP1.1和SOAP1.2 比较

  1. 目前WebService的协议主要有SOAP1.1和1.2。
  2. 两者的命名空间不同。

Soap1.1的命名空间:

   xmlns:soap=“http://schemas.xmlsoap.org/soap/envelope/

Soap1.2 命名空间:

    xmlns:soap="http://www.w3.org/2003/05/soap-envelope

 

 

  1. SOAP1.1版本与SOAP1.2版本在头信息上存在差异。
    1. SOAP1.1存在SOAPAction的请求头。
    2. SOAP1.2没有SOAPAction的请求头。

SOAP1.1的HTTP请求头:

POST /xe_cxf2.4_soap12_spring_web/ws/helloworldsoap12?wsdl HTTP/1.1
Content-Type:
text/xml; charset=UTF-8
Accept: */*
SOAPAction: ""
User-Agent: Apache CXF 2.4.0
Cache-Control: no-cache
Pragma: no-cache
Host: localhost:6767
Connection: keep-alive
Content-Length: 216

SOAP1.2的请求头:

POST /xe_cxf2.4_soap12_spring_web/ws/helloworldsoap12?wsdl HTTP/1.1
Content-Type:
application/soap+xml; charset=UTF-8
Accept: */*
User-Agent: Apache CXF 2.4.0
Cache-Control: no-cache
Pragma: no-cache
Host: localhost:6767
Connection: keep-alive
Content-Length:214

 

  1. 基于SOAP1.1生成的WSDL和基于SOAP1.2生成的WSDL也不一样。
  2. 在CXF中两种协议请求的方式也不一样。
    1. 1.1为content-Type:text/xm;charset=UTF-8
    2. 1.2为content-Type:application/soap+xml;charset=UTF-8

SOAP1.1和1.2的WSDL文件的差别:

l  在定义Service部分差别如下:

l  Soap1.1是以:soap:address定义。

l  Soap1.2是以:  soap12:address定义。-jdk1.6-api提供的webservice不支持1.2形式的访问。只对1.1支持

通过BindingType将项目转到1.2:

l  在类上面添加以下注解可以使用soap1.2的协议:

•    @BindingType(value=SOAPBinding.SOAP12HTTP_BINDING)

l  或在applicationContext.xml中使用binding

•    <jaxws:binding>

•             <soap:soapBindingversion="1.2" />

•       </jaxws:binding>

SOAP1.2的调用:

l  当使用了SOAP12以后,wsimport和Eclipse的WSExplorer都不可以正常使用了。

l  必须,使用cxf提供的wsdl2java工具生成本地代码。

l  生成本地代码后,通过cxf内置的拦截器,拦截到以下头信息说明是soap12.

 

SOAP11与SOAP12的调用关系:

比较好的软件都做了 向下兼容的实现 , 所以建议 soap1.2的服务器端 , 这样 客户端版本 就都可以进行调用

Cxf中两种协议请求的方式

Soap1.1以普通方式访问:

      使用JaxWsProxyFactoryBean

Soap1.2以指定wsdl地址和命名空间的形式访问:

      Serviceservice = Service.create(new URL(“wsdlUrl”),

                                                          new QName(“namespace”,”ServiceName”));

      SomeClass sc = service.getPort(newQName(“namespace”,”PortName”),

                                                         SomeClass.class);

     sc.someMethod(someParam);

通过Ajax形式访问:

1、指定contentType:’application/soap+xml;charset=“UTF-8”‘

2、组织使用XML数据,使用SOAP12的命名空间.

var str = '<soap12:Envelope xmlns:soap12=

"http://www.w3.org/2003/05/soap-envelope">'+

                   '<soap12:Body><ns2:sayHi xmlns:ns2="http://service.itcast.com/">'+

                   '<arg0>'+nm+'</arg0></ns2:sayHi></soap12:Body></soap12:Envelope>';

           $.ajax({

                 url:'<c:url value="/ws/greeting"/>',

                 contentType:'application/soap+xml;charset="UTF-8"',

                 dataType:'xml',

                 type:'post',

                 data:str,

                 success:function(data){

                      var vv = $(data).find("return").eq(0).text();

                      $("<div>").text(vv).css({border:'1px solid red',width:'500px',marginTop:'5px'})

                                       .appendTo($("body"));

                 }

           },"xml");

 

 

Webservice 相关工具

WebService监听工具:tcp/ip monitor

在企业里 , 上网都设置一个代理, 中间有一个代理服务器 , 再去访问外网 .

l  我们的代码不仅仅是向服务器发送的HTTP协议,更具体的说应该叫SOAP协议,它是WebService进行通信的基础。

l  为了获取SOAP数据发送和接收的格式。我们有必要使用一个工具来深入的了解WebService.

l  为了监控拦截请求头和响应头的具体数据,我们使用TCP/IP Monitor来拦截请求和响应的完整过程。

l  此工具在 myEclipse 有内置,使用TCP/IP Monitor-拦截HTTP请求头和响应头及Body部分:

l  此工具位于:window>show view>other>MyEclipseCommon(常用工具)>TCP/IPMonitor

 

使用WebServiceExplorer只可以看到SOAPXML数据,并看不到HTTP协议的头。

既然是用HTTPXML数据,就一定会有HTTP头,为了获取HTTP头,我们使用TCP/IP Monitor.

 

 

请求数据 :

响应数据:

Tcp/ip monitor 原理

前面的WSExplorer只参获取消息体部分。为了获取HTTP

请求的具体信息,我们可以使用monitor;因为SOAP是在HTTP的基础上发XML据,前面的XML数据已经可以获取到了,那么,既然是在HTTP上收发消息,就一定会有HTTP的头信息,那HTTP头信息又是怎么样的呢?

 

1      此工具,相当于一个代理商,启动后它将监听本地的某个端口,然后再将请求转发给指定的目标IP和端口。

1.1.1  获取到数据后,再将数据原封不动的返回给客户。在客户看来,永远首先访问的都应该是这个代理,否则

1.1.2  我们将看不到数据传输的过程。

1      配置选项:

1.1.1  在打开的TCP/IP Monitor界面上:view Menu(右上方向下的小箭头)>Properties>Add(右侧添加)

1.1.2  设置成以下属性:

1

u   local monitoring port(监听本地的端口号):9876,随意设置一个4位的端口号,一会将通过http://127.0.0.1:9876的形式访问

u   host name(要监听的服务器,如www.baidu.com):127.0.0.1 –因为本机发布了一个WebService所以监听本机IP.也可以是任意的主机。

u   Port(要监听的目标服务器的端口):6666  - 因为我们发布的WebService为http://127.0.0.1:6666/helloworld所以,6666是需要监听的端口号。

u   Type(监听的类型):

u   TCP/IP : 将使用原始地址继续访问下一个请求,如用户输入:http://127.0.0.1:9876/helloworld?wsdl此时将返回wsdl服务访问地址同前。

u   HTTP :将使用目标地址继续访问下一个请求。如用户输入: http://127.0.0.1:9876/helloworld?wsdl在请求方法时将使用http://127.0.0.1:6666/helloworld来访问sayHi方法。此种方式将不再会被代理。因为已经不是正在监听的端口号了。

u   在监听类型处,我们选择TCP/IP。

 

建议,将两种方式都设置一下,然后通过在地址栏输入:http://127.0.0.1:9876/helloworld?wsdl,在返回的wsdl文件中

查看:<soap:address location=“http:……”/>处地址的变化情况。

time out:设置访问不成功的连接时间,保持为0,即不设置。
在设置好后,点OK按扭,然后再点右方的Start按扭,监听便已经启动。

 

2

u   在MyEclipse的WebService上配置WSDL URL为:http://127.0.0.1:9876/helloworld?wsdl,注意使用的是MyEclipse TCP/IP Monitor的端口。而不是直接去访问我们发布的http://127.0.0.1:6666/helloworld?wsdl

u   在WebService Explorer上请求sayHi方法,传递参数,并查看http头信息和发送及返回的xml信息。

u   无论是MyEclipse WebService Explorer,Httpwatch,还是TCP/IP Monitor都是一些辅助工具。虽然对编写代码没有什么用处,但对我如何监控问题,发现问题的能力有所帮助。更能从工具的使用中,发现代码的问题进行调整或改进。

 

示例配置拦截本机到百度的请求:

拦截方式 : http(表现层) tcp/ip(传输层协议)

原理图

WS Explorer工具的使用:- web服务浏览器

使用此工具可以获取请求协议的格式和响应协议的格式。

      在MyEclipse的调用WebService并查看发出和收到的数据格式!

实现步骤:

1.   点击弹出对话窗口 , 输入调用服务的wsdl 地址

2. 输入正确的WSDL地址后,点确定,将显示所的对外暴露的方法:

3. 选择其中的一个方法,并向服务器发起请求:

此内容就可以使用在 ajax调用服务方式 , 给出 RequestBody所使用的数据 ,

一般使用ajax调用,应该是在已经获知了以下信息以后才去调用:

•  获知请求(request)的soap文本。

•  获知响应(response)soap文本。

 

在MyEclipse中调用WebService可以快速验证你的服务器端程序,从而省去了自己书写客户端。

1:这是发出的消息格式:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:q0="http://itcast.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

- <soapenv:Body>

- <q0:sayHi>

  <arg0>zhangsan同学</arg0>

  </q0:sayHi>

  </soapenv:Body>

  </soapenv:Envelope>

2:以下是接收到的XML格式

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">

- <S:Body>

- <ns2:sayHiResponse xmlns:ns2="http://itcast.com/">

  <return>你好:zhangsan同学,当前时间是:2011-05-07 10:15:20</return>

  </ns2:sayHiResponse>

  </S:Body>

  </S:Envelope>

3:上面的1和2就是SOAP(Simple Object Access Protocol)简单对像访问协议的格式。

 

 

 

 

 

0 0
原创粉丝点击