1. 程式人生 > >webservice呼叫和釋出

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")修改傳入引數的元素的父標籤名字