Webservice-1
- 一、認識webservice
什麼是服務?
1)現在的應用程式變得越來越複雜,甚至只靠單一的應用程式無法完成全部的工作。更別說只使用一種語言了。
2)大家在寫應用程式查詢資料庫時,並沒有考慮過為什麼可以將查詢結果返回給上層 的應用程式,甚至認為,這就是資料庫應該做的,其實不然,這是資料庫通過TCP/IP 協議與另一個應用程式進行交流的結果,而上層是什麼樣的應用程式,是用什麼語言,資料庫本身並不知道,它只知道接收到了一份協議,這就是SQL92查詢標準協議。
3) 既然資料庫可以依據某些標準對外部其他應用程式提供服務、而且不關心對方使用 什麼語言,那我們為什麼就不能實現跨平臺、跨語言的服務呢?只要我們用Java寫 的程式碼,可以被任意的語言所呼叫,我們就實現了跨平臺,跨語言的服務!
複雜的網路應用:
WebService定義: 顧名思義就是基於Web的服務。它使用Web(HTTP)方式,接收和響應外部系統的某種請求。從而實現遠端呼叫。
Webservice理解:我們可以呼叫網際網路上查詢天氣資訊Web服務,然後將它嵌入到我們的程式(C/S或B/S程式)當中來,當用戶從我們的網點看到天氣資訊時,他會認為我們為他提供了很多的資訊服務,但其實我們什麼也沒有做,只是簡單了呼叫了一下伺服器上的一段程式碼而已
- 二、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步驟
- 開啟WSDL文件
- 從下往上讀WSDL文件,先找到Services(服務訪問點集合),根據Services裡面binding屬性找到binding元素,再根據binding元素的type屬性找到繫結的portType(服務類)
- 根據WSDL的地址生成客戶端程式碼wsimport -s . -p com.rl.trans d:/wsCode/EnglishChinese.wsdl
- 把客戶端程式碼拷貝到專案中
- 建立服務訪問點集合物件
- 根據服務訪問點獲得服務類
- 呼叫服務類的方法
- 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.*包中。
主要類有:
- @WebService - 它是一個註解,用在類上指定將此類釋出成一個webservice服務.
- Endpoint – 此類為端點服務類,它的方法publish用於將一個已經添加了@WebService註解物件繫結到一個地址的埠上。Endpoint是jdk提供的一個專門用於釋出服務的類,它的publish方法接收兩個引數,一個是本地的服務地址,二是提供服務的類。它位於javax.xml.ws.*包中。
static Endpoint.publish(String address, Object implementor) 在給定地址處針對指定的實現者物件建立併發布端點。stop方法用於停止服務。
其他注意事項:
- 給類新增上@WebService註解後,類中所有的非靜態方法都將會對外公佈。不支援靜態方法,final方法。
- 如果希望某個方法(非static,非final)不對外公開,可以在方法上新增@WebMethod(exclude=true),阻止對外公開。
- 如果一個類上,被添加了@WebService註解,則必須此類至少有一個可以公開的方法,否則將會啟動失敗。
- 服務類中不能沒有方法
- @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")修改傳入引數的元素的父標籤名字