webservice调用和发布

原文地址 :https://blog.csdn.net/xnf1991/article/details/52262135

1. 认识webservice

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

Webservice理解:我们可以调用互联网上查询天气信息Web服务,然后将它嵌入到我们的程序(C/S或B/S程序)当中来,当用户从我们的网点看到天气信息时,他会认为我们为他提供了很多的信息服务,但其实我们什么也没有做,只是简单了调用了一下服务器上的一段代码而已。WebSerice可以将你的服务(一段代码)发布到互联网上让别人去调用,也可以调用别人机器上发布的WebService,就像使用自己的代码一样.。

2. Webservice调用

2.1webservice几个名词

名词1:XML. Extensible Markup Language -扩展性标记语言

         XML,用于传输格式化的数据,是Web服务的基础。

         namespace-命名空间。

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

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

名词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部分,包含要执行的服务器的方法。和发送到服务器的数据。

名词4:UDDI (Universal Description, Discovery, and Integration) 是一个主要针对Web服务供应商和使用者的新项目。

在用户能够调用Web服务之前,必须确定这个服务内包含哪些商务方法,找到被调用的接口定义,还要在服务端来编制软件,UDDI是一种根据描述文档来引导系统查找相应服务的机制。

UDDI利用SOAP消息机制(标准的XML/HTTP)来发布,编辑,浏览以及查找注册信息。

它采用XML格式来封装各种不同类型的数据,并且发送到注册中心或者由注册中心来返回需要的数据。

2.2 webservice服务网址

Webservice服务网站:http://www.webxml.com.cn

2.3  WSDL解析

Wsdl文档从下往上读

Types - 数据类型定义的容器,它使用某种类型系统(一般地使用XML Schema中的类型系统)。(入参和出参的数据类型)
 Message - 通信消息的数据结构的抽象类型化定义。使用Types所定义的类型来定义整个消息的数据结构(入参和出参)。
 Operation - 对服务中所支持的操作的抽象描述,一般单个Operation描述了一个访问入口的请求/响应消息对(方法)。
 PortType- 对于某个访问入口点类型所支持的操作的抽象集合,这些操作可以由一个或多个服务访问点来支持(服务类)。
Binding- 特定服务访问点与具体服务类的绑定(不看内容,看关系)。
Port- 定义为webservice单个服务访问点。
Service-相关服务访问点的集合。

2.4生成客户端代码方式调用webservice

1. wsimport是jdk自带的,可以根据wsdl文档生成客户端调用代码的工具.当然,无论服务器端的WebService是用什么语言写的,都将在客户端生成Java代码,服务器端用什么写的并不重要。

3. wsimport.exe位于JAVA_HOME\bin目录下.

常用参数为:-d<目录>  - 将生成.class文件。默认参数。

•    -s<目录>  -将生成.java文件和class文件。

•    -p<生成的新包名> -将生成的类,放于指定的包下。

•    (wsdlurl) - http://server:port/service?wsdl,必须的参数。

示例:

C:/> wsimport –s . http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl

4.注意:-s不能分开,-s后面有个小点,用于指定源代码生成的目录。点即当前目录。

如果使用了-s参数则会在目录下生成两份代码,一份为.class代码。一份为.java代码。

.class代码,可以经过打包以后使用。.java代码可以直接Copy到我们的项目中运行。

调用webservice步骤

1)      打开WSDL文档

2)      从下往上读WSDL文档,先找到Services(服务访问点集合),根据Services里面binding属性找到binding元素,再根据binding元素的type属性找到绑定的portType(服务类)

3)      根据WSDL的地址生成客户端代码wsimport -s . -p com.rl.trans d:/wsCode/EnglishChinese.wsdl

4)      把客户端代码拷贝到项目中

5)      创建服务访问点集合对象

6)      根据服务访问点获得服务类

7)      调用服务类的方法

3. jdk发布webservice服务

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

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

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

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

主要类有:

a)      @WebService - 它是一个注解,用在类上指定将此类发布成一个webservice服务,如下所示:

@WebService

public class HelloServer {

/**

 * 1.需要方法权限是public

 * 2.不能是final类型

 * 3.方法不能是静态的

 * 4.服务类至少有一个方法

 * @paramname

 *@return

 */

@WebMethod(exclude=false)

public String sayHello(String name){

           return name + " hello!";

}

@WebMethod(exclude=false)

public String sayBye(String name){

           return name + " bye!";

}

}

b)      Endpoint – 此类为端点服务类,它的方法publish用于将一个已经添加了@WebService注解对象绑定到一个地址的端口上。Endpoint是jdk提供的一个专门用于发布服务的类,它的publish方法接收两个参数,一个是服务的地址,二是提供服务的类。它位于javax.xml.ws.*包中。

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

   public static void main(String[] args) {

      //jdk发布webservice服务,第一个参数服务地址,第二个参数具体服务类

      Endpoint.publish("http://127.0.0.1:8080/hello",new HelloServer());

   }

stop方法用于停止服务。

其他注意事项:

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

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

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

4)      服务类中不能没有方法

5)      @WebMethod(exclude=true)屏蔽方法

4.其他调用webservice的方式

4.1使用ajax+xml调用

var xhr;

function invoke(){

   if(window.ActiveXObject){

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

   }else{

      xhr = new XMLHttpRequest();

   }

   //指定请求地址

   var url ="http://127.0.0.1:7777/hello?wsdl";

   //定义请求类型和地址和异步

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

   //设置Content-Type

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

   //指定回调方法

   xhr.onreadystatechange = back;

  

   var textVal =document.getElementById("mytext").value;

   //组装消息体的数据

   var data = '<soapenv:Envelopexmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"xmlns:q0="http://server.hm.com/"xmlns:xsd="http://www.w3.org/2001/XMLSchema"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'

   +'<soapenv:Body>'

   +'<q0:sayHello>'

   +'<arg0>'+textVal+'</arg0>'

   +'</q0:sayHello>'

   +'</soapenv:Body>'

   +'</soapenv:Envelope>';

   xhr.send(data);

}

function back(){

   if(xhr.readyState == 4){

      if(xhr.status == 200){

        var doc =xhr.responseXML;

        alert(doc);

        alert(xhr.responseText);

        var tag =doc.getElementsByTagName("return")[0];

        alert(tag)

       

   }

}

}

4.2通过HttpURLConnection调用

//创建url地址

      URL url = new URL("http://127.0.0.1:8080/hello?wsdl");

      //打开连接

      URLConnection conn = url.openConnection();

      //转换成HttpURL

      HttpURLConnection httpConn = (HttpURLConnection) conn;

      //打开输入输出的开关

      httpConn.setDoInput(true);

      httpConn.setDoOutput(true);

      //设置请求方式

      httpConn.setRequestMethod("POST");

      //设置请求的头信息

      httpConn.setRequestProperty("Content-type","text/xml;charset=UTF-8");

      //拼接请求消息

      String data = "<soapenv:Envelopexmlns:soapenv=" +

           "\"http://schemas.xmlsoap.org/soap/envelope/\"" +

           "xmlns:q0=\"http://server.rl.com/\"" +

           "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"" +

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

           +"<soapenv:Body>"

           +"<q0:sayHello>"

           +"<arg0>renliang</arg0>"

          +"</q0:sayHello>"

          +"</soapenv:Body>"

          +"</soapenv:Envelope>";

      //获得输出流

      OutputStream out = httpConn.getOutputStream();

      //发送数据

      out.write(data.getBytes());

      //判断请求成功

      if(httpConn.getResponseCode() == 200){

        //获得输入流

        InputStream in = httpConn.getInputStream();

        //使用输入流的缓冲区

        BufferedReader reader = new BufferedReader(new InputStreamReader(in));

        StringBuffer sb = new StringBuffer();

        String line = null;

        //读取输入流

        while((line = reader.readLine()) !=null){

           sb.append(line);

        }

        //创建sax的读取器

        SAXReader saxReader = new SAXReader();

        //创建文档对象

        Document doc = saxReader.read(new StringReader(sb.toString()));

        //获得请求响应return元素

        List<Element> eles = doc.selectNodes("//return");

        for(Element ele : eles){

           System.out.println(ele.getText());

      }

5.复杂消息请求

对于ajax和HttpURLConnection调用webservice有一个缺点是都需要自己来组装消息体,这对于复杂的web请求就比较麻烦,所以一般都会用生成客户端代码的方式来调用webservice,下面是的例子是通过添加person这个实体对象来发送请求。

创建一个实体person:

public class Person {

  

   private int id;

  

   private Stringname;

  

   private int age;

  

   private Stringaddress;

    get和set方法…

}

服务端代码:

@WebService

public class PersonServer {

  

   List<Person> pList = new ArrayList<Person>();

  

   /**

    * 添加人

    * @param person

    */

   public void addPerson(Person person){

      pList.add(person);

   }

   /**

    * 获得所有的人

    * @return

    */

   public List<Person> getPersonAll(){

      return pList;

   }

  

   public static void main(String[] args) {

      Endpoint.publish("http://127.0.0.1:6060/person",new PersonServer());

   }

在F:/wsCode/生成客户端代码:

wsimport–s . –p com.rl.person http://127.0.0.1:6060/person?wsdl

客户端调用web服务:

public class TestPersonClient {

  

   public static void main(String[] args) {

     

      //创建服务访问点集合

            PersonServerService pss = new PersonServerService();

            //根据服务访问点获得绑定的类

            PersonServer server = pss.getPersonServerPort();

            //调用具体业务逻辑

            Person person = new Person();

            person.setId(1);

            person.setName("zhaoliu");

            person.setAge(20);

            person.setAddress("xiangyashan");

           

            Person person1 = new Person();

            person1.setId(2);

            person1.setName("tianqi");

            person1.setAge(25);

            person1.setAddress("gaolaozhang");

           

            //调用添加人的webservice服务方法

            server.addPerson(person);

            server.addPerson(person1);

            //调用查询所有人的webservice服务方法

            List<Person> pList = server.getPersonAll();

            for(Person p : pList){

                System.out.println("id: "+p.getId()+"  name:"+p.getName()+"  age:"+p.getAge() + " address:"+p.getAddress());

            }

   }

6.wsdl文档元素名称修改

自动生成的文档的名字有时不规范,可以手动进行修改。

        @WebService(

        portName="myHelloService",修改端口名字

        serviceName="HelloServices",修改服务访问点集合名字

        name="HelloService",修改服务类的名字

        targetNamespace="hello.test.com"修改命名空间名字

      )

@WebMethod(exclude=false)

public  @WebResult(name="byeResult") String  sayBye(@WebParam(name="personName ") String name){

      return name +" bye!";

   }

  

@WebResult(name="byeResult")修改返回值的元素的父标签名字

@WebParam(name="personName")修改传入参数的元素的父标签名字

猜你喜欢

转载自blog.csdn.net/baidu_32739019/article/details/81110279