1. 程式人生 > >Webservice-1

Webservice-1

 

  • 一、認識webservice

什麼是服務

 

1)現在的應用程式變得越來越複雜,甚至只靠單一的應用程式無法完成全部的工作。更別說只使用一種語言了。

2)大家在寫應用程式查詢資料庫時,並沒有考慮過為什麼可以將查詢結果返回給上層               的應用程式,甚至認為,這就是資料庫應該做的,其實不然,這是資料庫通過TCP/IP          協議與另一個應用程式進行交流的結果,而上層是什麼樣的應用程式,是用什麼語言,資料庫本身並不知道,它只知道接收到了一份協議,這就是SQL92查詢標準協議。

3) 既然資料庫可以依據某些標準對外部其他應用程式提供服務、而且不關心對方使用    什麼語言,那我們為什麼就不能實現跨平臺、跨語言的服務呢?只要我們用Java寫    的程式碼,可以被任意的語言所呼叫,我們就實現了跨平臺,跨語言的服務!

 

複雜的網路應用

 

 

 

WebService定義: 顧名思義就是基於Web的服務。它使用Web(HTTP)方式,接收和響應外部系統的某種請求。從而實現遠端呼叫。

 

Webservice理解:我們可以呼叫網際網路上查詢天氣資訊Web服務,然後將它嵌入到我們的程式(C/S或B/S程式)當中來,當用戶從我們的網點看到天氣資訊時,他會認為我們為他提供了很多的資訊服務,但其實我們什麼也沒有做,只是簡單了呼叫了一下伺服器上的一段程式碼而已

。WebSerice可以將你的服務(一段程式碼)釋出到網際網路上讓別人去呼叫,也可以呼叫別人機器上釋出的WebService,就像使用自己的程式碼一樣.。

  • 二、Webservice呼叫
  • 2.1學習webservice呼叫的預備知識

名詞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部分,包含要執行的伺服器的方法。和傳送到伺服器的資料。

  • 2.2 webservice服務網址

Webservice服務網站:http://www.webxml.com.cn

 

  • 2.3WSDL解析

Wsdl文件從下往上讀

Types - 資料型別定義的容器,它使用某種型別系統(一般地使用XML Schema中的型別系統)。(入參和出參的資料型別)
 Message - 通訊訊息的資料結構的抽象型別化定義。使用Types所定義的型別來定義整個訊息的資料結構(入參和出參)。
 Operation - 對服務中所支援的操作的抽象描述,一般單個Operation描述了一個訪問入口的請求/響應訊息對(方法)。
 PortType - 對於某個訪問入口點型別所支援的操作的抽象集合,這些操作可以由一個或多個服務訪問點來支援(服務類)。
Binding - 特定服務訪問點與具體服務類的繫結(不看內容,看關係)。
Port - 定義為webservice單個服務訪問點。

 Service- 相關服務訪問點的集合。

 

  • 2.4生成客戶端程式碼

1. wsimport是jdk自帶的,可以根據wsdl文件生成客戶端呼叫程式碼的工具.當然,無論

2. 伺服器端的WebService是用什麼語言寫的,都將在客戶端生成Java程式碼.伺服器端用什麼寫的並不重要.

3. wsimport.exe位於JAVA_HOME\bin目錄下.

常用引數為:-d<目錄>  - 將生成.class檔案。預設引數。

    • -s<目錄>  - 將生成.java檔案和class檔案。
    • -p<生成的新包名> -將生成的類,放於指定的包下。
    • (wsdlurl) - http://server:port/service?wsdl,必須的引數。

示例:

C:/> wsimport –s . http://192.168.0.100/one?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. 呼叫服務類的方法
  • 2.5訊息體

1) SOAP1.1請求訊息體

POST /WebServices/MobileCodeWS.asmx HTTP/1.1

Host: webservice.webxml.com.cn

Content-Type: text/xml; charset=utf-8

Content-Length: length

SOAPAction: "http://WebXml.com.cn/getMobileCodeInfo"

 

<?xml version="1.0" encoding="utf-8"?>

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

  <soap:Body>

    <getMobileCodeInfo xmlns="http://WebXml.com.cn/">

      <mobileCode>string</mobileCode>

      <userID>string</userID>

    </getMobileCodeInfo>

  </soap:Body>

</soap:Envelope>

2)SOAP1.1相應訊息體

 

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length
 
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <getMobileCodeInfoResponse xmlns="http://WebXml.com.cn/">
      <getMobileCodeInfoResult>string</getMobileCodeInfoResult>
    </getMobileCodeInfoResponse>
  </soap:Body>
</soap:Envelope>
  • 三、jdk釋出webservice服務

注意:用Jdk1.6.0_21以後的版本釋出一個WebService服務.

說明:      在JDK1.6中JAX-WS規範定義瞭如何釋出一個webService服務。

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

與Web服務相關的類,都位於javax.xml.ws.*包中。

主要類有:

  1. @WebService - 它是一個註解,用在類上指定將此類釋出成一個webservice服務.
  2. Endpoint – 此類為端點服務類,它的方法publish用於將一個已經添加了@WebService註解物件繫結到一個地址的埠上。Endpoint是jdk提供的一個專門用於釋出服務的類,它的publish方法接收兩個引數,一個是本地的服務地址,二是提供服務的類。它位於javax.xml.ws.*包中。

static Endpoint.publish(String address, Object implementor) 在給定地址處針對指定的實現者物件建立併發布端點。stop方法用於停止服務。

其他注意事項:

  1. 給類新增上@WebService註解後,類中所有的非靜態方法都將會對外公佈。不支援靜態方法,final方法。
  2. 如果希望某個方法(非static,非final)不對外公開,可以在方法上新增@WebMethod(exclude=true),阻止對外公開。
  3. 如果一個類上,被添加了@WebService註解,則必須此類至少有一個可以公開的方法,否則將會啟動失敗。
  4. 服務類中不能沒有方法
  5. @WebMethod(exclude=true)遮蔽方法

使用myeclipse檢視訊息體

 

 

  • 四、其他呼叫webservice的方式
  • 4.1使用ajax呼叫

 

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:Envelope xmlns: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.通過URLConnection呼叫

 

//建立url地址

      URL url = new URL("http://192.168.1.104:8080/hello");

      //開啟連線

      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:Envelope xmlns: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());

      }

  • 五、複雜訊息請求

@WebService

public class TestComplexServer {

  

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

  

  

   public void addPerson(Person person){

      pList.add(person);

   }

  

   public List<Person> getPersonList(){

      return pList;

   }

  

 

   public static void main(String[] args) {

      Endpoint.publish("http://192.168.1.104:8888/person", new TestComplexServer());

   }

}

  • 六、監聽器

用於檢視請求和相應的訊息

 

  • 七、wsdl文件元素名稱修改

自動生成的文件的名字有時不規範,可以手動進行修改。

        @WebService(

        portName="myHelloService",修改埠名字

        serviceName="HelloServices",修改服務訪問點集合名字

        name="HelloService",修改服務類的名字

        targetNamespace="hello.rl.com" 修改名稱空間名字

      )

 

@WebResult(name="sirHello")修改返回值的元素的父標籤名字

@WebParam(name="sir")修改傳入引數的元素的父標籤名字