Web-Service-常用监听器&&注解修改WSDL

WebService监听工具:

之前我们使用过HttpWatch获取的HTTP的调用过程,并获得了HTTP的请求头及其他请求的详细信息。

既然WebServie也是通过HTTP进行通信的,能不使用HTTPWatch来获取它的请求过程呢?


我们的代码不仅仅是向服务器发送的HTTP协议,更具体的说应该叫SOAP协议,它是WebService进行通信的基
础。
为了获取SOAP数据发送和接收的格式。我们有必要使用一个工具来深入的了解WebService.

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

1:简单的说,SOAP就是在HTTP的基础上传输XML数据,以实现远程调用。

    因为HTTPXML格式的数据已经被广泛的应用。而SOAP又架构在这两种技术之上,所以WebService为什么会流行也就不难理解了。

2:老生常谈,无论你的服务端是什么语言书写的,只要接收SOAP协议的XML数据,并返回SOAP协议的XML数据,就可以被任何语言调用。

3、以下是通过纯ajax向服务器发送XML数据并解析的代码:

<%@page language="java" import="java.util.*"pageEncoding="UTF-8"%>

 

 

 

   

通过Ajax向服务器发送XML数据

   

 

 

---

服务器使用jaxp进行解析

packagecn.itcast;

importjava.io.IOException;

importjava.io.InputStream;

importjava.io.PrintWriter;

importjavax.servlet.ServletException;

importjavax.servlet.http.HttpServlet;

importjavax.servlet.http.HttpServletRequest;

importjavax.servlet.http.HttpServletResponse;

importjavax.xml.parsers.DocumentBuilder;

importjavax.xml.parsers.DocumentBuilderFactory;

importorg.w3c.dom.Document;

importorg.w3c.dom.Element;

importorg.w3c.dom.NodeList;

/**

 * 接收XML数据使用jaxp进行解析

 * @author

 */

publicclass One extends HttpServlet{

  public void doGet(HttpServletRequestrequest, HttpServletResponseresponse)

  throws ServletException,IOException{

  doPost(request,response);

  }

  public void doPost(HttpServletRequestrequest, HttpServletResponseresponse)

  throws ServletException,IOException{

  //获取输入流,如果在输出,请在组成String时使用UTF-8

  InputStreamin = request.getInputStream();

  String names = "";

  // 使用JAXP解析

  try {

  DocumentBuilderFactoryfactory = DocumentBuilderFactory

  .newInstance();

  DocumentBuilderbuilder = factory.newDocumentBuilder();

  Document dom= builder.parse(in);

  NodeList nl = dom.getElementsByTagName("name");

  for(inti=0;i<nl.getLength();i++){

  Element el = (Element)nl.item(i);

  String name = el.getTextContent();

  System.err.println(">>:"+name);

  names +=name;

  }

  } catch (Exception e) {

  throw new RuntimeException(e.getMessage(),e);

  }

  response.setContentType("text/xml;charset=UTF-8");

  PrintWriterout = response.getWriter();

  out.print("{\"name\":\""+names+"\"}");

  }

}

-----以下通过jQuery+Dom4j实现发XML数据--------

   javascript"src="js/jquery-1.6.2.js">

    javascript">

    $(function(){

    $("#jq").click(function(){

    varxml = "" +

    "王健A张三";

    alert(xml);

    $.ajax({

    url:'Two',

    type:'post',

    dataType:'json',//设置返回的数据类型

    data:xml,//直接发xml数据

    contentType:'application/x-www-form-urlencoded',

    success:function(data){

    alert("返回的信息是:"+data.name);

    },

    complete:function(http,textStatus){

    alert("over..."+textStatus);

    }

    });

    });

    });

   

----------------------------

packagecn.itcast;

importjava.io.IOException;

importjava.io.InputStream;

importjava.io.PrintWriter;

importjava.util.Iterator;

importjavax.servlet.ServletException;

importjavax.servlet.http.HttpServlet;

importjavax.servlet.http.HttpServletRequest;

importjavax.servlet.http.HttpServletResponse;

importorg.dom4j.Document;

importorg.dom4j.Element;

importorg.dom4j.io.SAXReader;

/**

 * JQuery+Dom4j

 * @author xx

 */

publicclass Two extends HttpServlet{

  public void doPost(HttpServletRequestrequest, HttpServletResponseresponse)

  throws ServletException,IOException{

  String result = "";

  //中文newString(b,0,len,"UTF-8")

  InputStreamin = request.getInputStream();

  //以下用dom4j解析

  SAXReadersax = new SAXReader();

  try {

  Document dom= sax.read(in);

  Element root = dom.getRootElement();

  Iterator it = root.elementIterator();

  while(it.hasNext()){

  String nm = it.next().getStringValue();

  System.err.println(nm);

  result+=nm;

  }

  } catch (Exception e) {

  throw new RuntimeException(e.getMessage(),e);

  }

  response.setContentType("text/html;charset=UTF-8");

  PrintWriterout = response.getWriter();

  //返回json数据

  out.print("{\"name\":\""+result+"\"}");

  }

}

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



Web-Service-常用监听器&&注解修改WSDL_第1张图片



Web-Service-常用监听器&&注解修改WSDL_第2张图片

1、将wsdl文件,保存成本地一样可以通过此工具访问远程服务。为file:///D:/abc.xml


Web-Service-常用监听器&&注解修改WSDL_第3张图片


Web-Service-常用监听器&&注解修改WSDL_第4张图片

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

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

<soapenv:Envelopexmlns: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>

-

 zhangsan同学

 

 soapenv:Body>

 soapenv:Envelope>

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

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

-<S:Body>

-http://itcast.com/">

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

 

 S:Body>

 S:Envelope>

3:上面的12就是SOAPSimpleObject Access Protocol)简单对像访问协议的格式。

Web-Service-常用监听器&&注解修改WSDL_第5张图片

1:我们已经说过了,WebService是通过向服务器发出XML格式的数据实现远程调用,然后服务器也返回XML数据给客户端,那么这个XML是什么格式的呢?

下面我将使用MyEclipse中的WebServiceExplorer工具向我们的WebService发起请求,并查看它的XML数据格式。

2:通过HttpWatchprofession Edition只可以看到获取wsdl文档的具体信息。

     且必须安装HttpWatchprofession Edition版本的才可以,如果是Basic版本的,将不会看到Stream(数据流)信息。

         



Web-Service-常用监听器&&注解修改WSDL_第6张图片


Web-Service-常用监听器&&注解修改WSDL_第7张图片







3、使用MyEclipseTCP/IPMonitor这个工具来查看具体的请求过程。

    TCP/IPMonitor不仅可以看到SOAP数据,还可以获取HTTP请求和接收的头信息。

    3.1、此工具位于:window>showview>other>MyEclipseCommon(常用工具)>TCP/IPMonitor

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

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

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

   3.3、配置选项:

           在打开的TCP/IPMonitor界面上:viewMenu(右上方向下的小箭头)>Properties>Add(右侧添加)

           设置成以下属性:

           步1

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

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

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

           Type(监听的类型)

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


        -- HTTP :将使用目标地址继续访问下一个请求。如用户输入: http://127.0.0.1:9876/helloworld?wsdl在请求方法时将使用http://127.0.0.1:6666/helloworld来访问sayHi方法。此

种方式将不再会被代理。因为已经不是正在监听的端口号了。

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

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

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

         timeout:设置访问不成功的连接时间,保持为0,即不设置。


             在设置好后,点
OK按扭,然后再点右方的Start按扭,监听便已经启动。

         步2

          在MyEclipseWebService上配置WSDLURL为:http://127.0.0.1:9876/helloworld?wsdl,注意使用的是MyEclipseTCP/IP Monitor的端口。而不是直接去访问我们发布的

http://127.0.0.1:6666/helloworld?wsdl

         

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


         无论是MyEclipseWebServiceExplorer,Httpwatch,还是TCP/IPMonitor都是一些辅助工具。虽然对编写代码没有什么用处,但对我如何监控问题,发现问题的能力有所帮助。

更能从工具的使用中,发现代码的问题进行调整或改进。

Web-Service-常用监听器&&注解修改WSDL_第8张图片



Web-Service-常用监听器&&注解修改WSDL_第9张图片


Web-Service-常用监听器&&注解修改WSDL_第10张图片


Web-Service-常用监听器&&注解修改WSDL_第11张图片

Web-Service-常用监听器&&注解修改WSDL_第12张图片


Web-Service-常用监听器&&注解修改WSDL_第13张图片


Web-Service-常用监听器&&注解修改WSDL_第14张图片


看董wsdl文件,能帮助我们顺利弄清如何调用一个WebService,以及它有哪些类的哪些方法可以调用。


1SOAPBinding(style=Style.DOCUMENTStype.RPC)指定了消息的格式,即相互交流以语言。此值默认为DOCUMENT。并在wsdl

件的soap:binding.type上出现。请大家注意观察。


(目前我的使用的WebService规范是基于jax-ws的,而rpc是基于jax-rpc的,已经过时。)


以下是wsdl文档的部分代码:


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


Style指定了消息格式


Transport的最后部分指定了使用什么样的协议。此处定义为http协议。


所以,binding部分,定义了如何调用,使用什么样的协议和消息格式,有什么样的方法可以调用。


portType又指定了一个可以调用的Java类,

请看本目录下的wsdl文件的图示说明!03_WSDL文件分析.bmp

--types定义了命名空间的信息,其中namespace是倒置的包名。


                                             schemaLocationxsd地址信息,可以拷贝此地址,并查看xsd的定义

开始的二行注释是Jax-ws的版本,及是由哪个jdk生成的。



Web-Service-常用监听器&&注解修改WSDL_第15张图片


Web-Service-常用监听器&&注解修改WSDL_第16张图片


1、上面所有的内容,都是由系统发布时自动生成的,那么如何才可以修改这个文档呢?



修改wsdl文件的内容:


WSDL文件的内容,一般由服务默认生成,但为了更好的向开发人员提供使用说明书,一般应做一些简单的修改。至少不应该暴露我们的包结构。而targetNamespace默认情

况下为倒置的包名,这已经暴露了我们的包结构。

通过在类文件上添加以下注解,可以修改wsdl生成的各元素,而不是直接去修改wsdl文件直接去修改wsdl文件是无

效的

WebService的注解包括:

@WebService-定义服务  --类上

@WebMethod-定义方法  - 方法

@WebResult-定义返回值 – 返回值

@WebParam-定义参数 – 参数 

1、另有:SOAPBinding-指定WebServiceSOAP协议的影射关系?


使用不同版本的Jdk对发布ws的影响.


1.5不支持.

1.6.0_20前版本必须使用完整注解.

1.6.0_21以后可以只使用@WebService对类进行注解.

2、关于namespace约定名的说明,@WebService(targetNameSpace=..)

targetNamespace

定义导出的服务接口的名域(namespace),默认是倒置的服务接口Java包名。如demo.cxf.UserService的名域将会是http://cxf.demo/


Web-Service-常用监听器&&注解修改WSDL_第17张图片


1:WebService的注解都位于javax.jws包下。
     主要包含以下几个注解(直接查看JDK文档,关于它里面的配置属性也直接看JDK6的文档。)
	我们只讨论以下加个注解:
	WebMethod 	WebParam 	WebResult 	WebService

2:以下是加了注解的示例:
package com.itcast;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.WebParam.Mode;
import javax.xml.ws.Endpoint;
/**
 * 一个加了很多注解的代码
 */
@WebService(name="myName",//对应portType name="myName"
portName="myPort",  //对应服务中的port name="myPort"
serviceName="myService",//对应service name="myService"
targetNamespace="http://leaf.com/mynamespace")//可以随意书写类似于java中的package
public class HelloWorld{
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@WebMethod(action="myAction",//定义一个soapAction="myAction"用于找到这个方法以执行
   operationName="myOperationName")//定义可以调用的方法,会生成相应类的具体方法,operation name=".."
public @WebResult(name="mySayHelloResult")String//定义返回值的名称
sayHello(){
return "HelloWorld";
}
@WebMethod(action="mySayHiAction",operationName="mySayHiOperationName")
public @WebResult(name="mySayHiResult")String sayHi(@WebParam(name="myParaName",
//将参数放到头信息中,用于保护参数,默认在body中
                                                      header=true,
  mode=Mode.IN)
String name){
String str = "你好:"+name+",当前时间是:"+sdf.format(new Date());
return str;
}

public static void main(String[] args) {
Endpoint.publish("http://127.0.0.1:6666/helloworld",new HelloWorld());
}
}


3:将上面的程序对外发布以后,我们通过MyEclipse的WebService Explorer来访问
你会发现和以前不一样的提示信息,但其实,仍然还是调用的那同一个方法。

4:请同学们在去观察SOAP请求和返回文档的修改。在MyEclipse WebService Explorer的返回信息窗口中点Soure即可以看到。观察变化加以分析。

5:再次使用wsimport –s . http://127.0.0.1:6666/helloworld?wsdl生成java代码然后调用,看看还是哪些类名吗?
以下是调用代码(可以用面目全非来形容,但完成的还是同样的工作。)
package com.leaf.mynamespace;
public class Main {
public static void main(String[] args) {
//通过分析wsdl可知从myService中调用getMyPort返回myName
MyName myName = new MyService().getMyPort();
//通过myName的mySayHiOperationName来调用sayHi方法
String str = myName.mySayHiOperationName("王健");
System.err.println(str);
}
}



Web-Service-常用监听器&&注解修改WSDL_第18张图片


Web-Service-常用监听器&&注解修改WSDL_第19张图片

Web-Service-常用监听器&&注解修改WSDL_第20张图片



Web-Service-常用监听器&&注解修改WSDL_第21张图片

Web-Service-常用监听器&&注解修改WSDL_第22张图片



package cn.leaf.two;
import java.util.Date;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.ws.Endpoint;
/**
 * 发布第一个web服务
 */
@WebService
(serviceName="WjService"//修改Service的名称,即:new WjService();
 ,name="One"//定义Port名称,即端口-new WjService().getOnePort();返回接口即One
 ,targetNamespace="http://wj.cn"//定义命名空间,默认为倒置的包名
 ,portName="one"//定义获取的方法,此值可以覆盖name的定义,即port name="getOne"
)
public class OneService{
	@WebMethod(operationName="sayHello"//修改方法名
		      )
	public
	   @WebResult(name="ReturnMsg")
		String sayHi(
				@WebParam(name="yourName")
				String name){
		return name+",你好,现在时间是:"+new Date();
	}
	public static void main(String[] args) throws Exception {
		//发布服务
		Endpoint ed= Endpoint.publish("http://127.0.0.1:9999/one",
					new OneService());
		System.err.println("服务发布成功");
	}
}


Web-Service-常用监听器&&注解修改WSDL_第23张图片





你可能感兴趣的:(Web,Service)