Webservice就是一種遠程調用技術,它的做用就是從遠程系統中獲取業務數據。javascript
客戶端經過網絡通訊協議訪問服務端,網絡協議包括TCP和UDP兩大通訊協議:
TCP是一種面向鏈接的協議,提供可靠的數據傳輸,通常服務質量要求比較高的狀況,使用這個協議。TCP支持的應用協議主要有:Telnet、FTP、SMTP、HTTP等;
UDP用戶數據報協議,是一種無鏈接的傳輸層協議,提供面向事務的簡單不可靠信息傳送服務。UDP支持的應用層協議主要有:NFS(網絡文件系統)、SNMP(簡單網絡管理協議)、DNS(主域名稱系統)、TFTP(通用文件傳輸協議)等。
客戶服務器模式早期主要應用於c/s應用,web興起後主要應用於b/s應用,b/s比c/s的好處就在於b/s是基於瀏覽器客戶端訪問服務端。
課程安排:css
Web service 即web服務,它是一種跨編程語言和跨操做系統平臺的遠程調用技術即跨平臺遠程調用技術。html
詳解以下:java
JAVA 中共有三種WebService 規範,分別是JAX-WS(JAX-RPC)、JAXM&SAAJ、JAX-RS。
下面來分別簡要的介紹一下這三個規範。
1、JAX-WS(小公司使用)
JAX-WS 的全稱爲 Java API for XML-Based Webservices ,早期的基於SOAP 的JAVA 的Web 服務規範JAX-RPC(Java API For XML-Remote Procedure Call),目前已經被JAX-WS規範取代。從java5開始支持JAX-WS2.0版本,Jdk1.6.0_13之後的版本支持2.1版本,jdk1.7支持2.2版本。
二、JAXM&SAAJ(不經常使用)
JAXM(JAVA API For XML Message)主要定義了包含了發送和接收消息所需的API,SAAJ(SOAP With Attachment API For Java,JSR 67)是與JAXM 搭配使用的API,爲構建SOAP 包和解析SOAP 包提供了重要的支持,支持附件傳輸等,JAXM&SAAJ 與JAX-WS 都是基於SOAP 的Web 服務,相比之下JAXM&SAAJ 暴露了SOAP更多的底層細節,編碼比較麻煩,而JAX-WS 更加抽象,隱藏了更多的細節,更加面向對象,實現起來你基本上不須要關心SOAP 的任何細節。
三、JAX-RS(大公司使用)
JAX-RS 是JAVA 針對REST(Representation State Transfer)風格制定的一套Web 服務規範,因爲推出的較晚,該規範(JSR 311,目前JAX-RS 的版本爲1.0)並未隨JDK1.6 一塊兒發行。
服務端:發佈一個天氣查詢服務,接收客戶端城市名稱,返回天氣數據給客戶端。
客戶端:發送城市名稱給服務端,接收服務端的返回天氣數據,打印出來。web
JDK:1.8
Eclipse:Oxygenajax
開發步驟:
第一步:建立SEI(Service Endpoint Interface)接口,本質上就是Java接口編程
package com.itheima.webservice.jaxws.ws;
/*
* SEI接口
*/
public interface WeatherInterface {
public String queryWeather(String cityName);
}
第二步:建立SEI實現類,在實現類上加入註解@WebService設計模式
package com.itheima.webservice.jaxws.ws;
import javax.jws.WebService;
@WebService // @WebService表示該類是一個服務類,須要發佈其中的public的方法
public class WeatherInterfaceImpl implements WeatherInterface {
@Override
public String queryWeather(String cityName) {
System.out.println("from client..." + cityName);
String weather = "晴";
return weather;
}
}
第三步:發佈服務,Endpoint發佈服務,publish方法,兩個參數:1.服務地址;2.服務實現類瀏覽器
package com.itheima.webservice.jaxws.ws;
import javax.xml.ws.Endpoint;
public class WeatherServer {
public static void main(String[] args) {
// Endpoint 發佈服務
// 參數解釋:
// 1.address - 服務地址
// 2.implementor - 服務實現類
Endpoint.publish("http://127.0.0.1:12345/weather", new WeatherInterfaceImpl());
}
}
第四步:測試Webservice服務是否發佈成功,經過閱讀使用說明書,肯定客戶端調用的接口、方法、參數和返回值存在,證實服務發佈成功。服務器
以下圖所示:
一、
開發步驟:
示例代碼以下:
package com.itheima.webservice.jaxws.ws.client;
import com.itheima.webservice.jaxws.ws.WeatherInterfaceImpl;
import com.itheima.webservice.jaxws.ws.WeatherInterfaceImplService;
/*
* 天氣查詢客戶端
*/
public class WeatherClient {
public static void main(String[] args) {
// 建立服務視圖
WeatherInterfaceImplService weatherInterfaceImplService = new WeatherInterfaceImplService();
// 獲取服務實現類
WeatherInterfaceImpl weatherInterfaceImpl = weatherInterfaceImplService.getPort(WeatherInterfaceImpl.class);
// 調用查詢方法,打印
String weather = weatherInterfaceImpl.queryWeather("北京");
System.out.println(weather);
}
}
客戶端效果以下圖所示:
詳解以下:
<service> 服務視圖:webservice的服務結點,它包括了服務端點port(通常會有多個服務端點)。
<binding> 爲每一個服務端點port定義消息格式和協議細節。
<portType> 服務端點類型:描述 web service可被執行的操做方法,以及相關的消息,經過binding指向portType。
<message> 定義一個操做(方法)的數據參數(可有多個參數)。
<types> 定義 web service 使用的所有數據類型。
從下往上讀:先找到服務視圖,經過binging找到protType,找到了protType就找到了咱們要調用的webservice方法。
WSDL的文檔結構圖以及WSDL的閱讀方式以下圖所示;
必需有 envelope 元素
,此元素將整個 XML 文檔標識爲一條 SOAP 消息。必需有 body 元素
,包含全部的調用和響應信息。在MyEcplise中如何進行配置呢?步驟以下:
Windows --> Show View --> Other…
請求:
......
POST /weather HTTP/1.1
Accept: text/xml, multipart/related
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://ws.jaxws.webservice.itheima.com/WeatherInterfaceImpl/queryWeatherRequest"
User-Agent: JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e
Host: 127.0.0.1:54321
Connection: keep-alive
Content-Length: 224
<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body><ns2:queryWeather xmlns:ns2="http://ws.jaxws.webservice.itheima.com/">
<arg0>北京</arg0></ns2:queryWeather>
</S:Body>
</S:Envelope>
響應:
......
HTTP/1.1 200 OK
Date: Thu, 20 Sep 2018 07:44:22 GMT
Transfer-encoding: chunked
Content-type: text/xml; charset=utf-8
<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body><ns2:queryWeatherResponse xmlns:ns2="http://ws.jaxws.webservice.itheima.com/">
<return>晴</return></ns2:queryWeatherResponse>
</S:Body>
</S:Envelope>
請求:
......
POST /weather HTTP/1.1
Accept: application/soap+xml, multipart/related
Content-Type: application/soap+xml; charset=utf-8;action="http://ws.jaxws.webservice.itheima.com/WeatherInterfaceImpl/queryWeatherRequest"
User-Agent: JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e
Host: 127.0.0.1:54321
Connection: keep-alive
Content-Length: 222
<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope">
<S:Body><ns2:queryWeather xmlns:ns2="http://ws.jaxws.webservice.itheima.com/">
<arg0>北京</arg0></ns2:queryWeather>
</S:Body>
</S:Envelope>
響應:
......
HTTP/1.1 200 OK
Date: Thu, 20 Sep 2018 09:05:06 GMT
Transfer-encoding: chunked
Content-type: application/soap+xml; charset=utf-8
<?xml version='1.0' encoding='UTF-8'?>
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope">
<S:Body><ns2:queryWeatherResponse xmlns:ns2="http://ws.jaxws.webservice.itheima.com/">
<return>晴</return></ns2:queryWeatherResponse>
</S:Body>
</S:Envelope>
什麼是webservice?
什麼是遠程調用技術?答:系統和系統之間的調用,從遠程系統當中獲取業務數據。
Webservice是web服務,他是用http傳輸SOAP協議數據的一種遠程調用技術。
Webservice入門程序
服務端
第一步:建立SEI接口
第二步:建立SEI實現類,要在類上加入註解:@WebService,做用是標識這個類是服務類,要發佈裏面的public方法。
第三步:發佈服務,Endpoint的publish方法,有2兩個參數:1.服務地址 2.實現類實例
第四步:測試服務是否發佈成功,經過閱讀使用說明書,肯定服務接口、方法、參數和返回值存在,說明服務發佈成功。
WSDL地址:服務地址+」?wsdl」,http://127.0.0.1:54321/weather?wsdl
WSDL閱讀方式,從下往上,service --> binding --> portType --> 其中有接口、方法、參數和返回值
客戶端
第一步:使用wsimport命令生成客戶端代碼
第二步:根據使用說明書,使用客戶端調用服務端
建立服務視圖,視圖是從service的name屬性獲取
獲取服務實現類,從portType的name屬性獲取
調用查詢方法,從portType下的operation標籤的name屬性獲取
優缺點:
優勢:發送方式採用http的post,http默認端口是80,因此跨防火牆。
數據封裝使用XML格式,XML是跨平臺,因此webservice能夠跨平臺。
Webservice支持面向對象開發。
缺點:使用XML封裝數據,須要額外傳輸其餘標籤,性能較差。
Webservice應用場景
軟件集成和複用
適用場景:
發佈服務(對內/對外),不考慮性能,不考慮客戶端類型,建議使用webservice
服務端已肯定使用webservice,客戶端只能使用webservice
不適用場景:
考慮性能時,不建議使用webservice
同構程序下,不建議使用webservice,好比:客戶端服務端都是java開發,建議使用Java RMI,Java的RMI一樣能夠實現遠程調用,並且性能比webservice好不少。
WSDL
定義:WSDL即Web服務描述語言,他是webservice服務端的使用說明書,它說明服務端接口、方法、參數和返回值,它是隨服務發佈成功,自動生成的,無需編寫。
文檔結構:
service
binding
portType
message
types
閱讀方式:從下往上
SOAP
定義:SOAP即簡單對象訪問協議,它是使用http發送的XML格式的數據,跨平臺、跨防火牆,它不是webservice的專有協議。
SOAP = http + xml
協議的格式:
必須項:envelope和body
非必須項:header和fault
SOAP1.1和1.2區別:
相同點:
都使用http的POST發送請求
協議的格式都相同:都有envelope標籤和body標籤
不一樣點:
Content-type數據類選不一樣:
SOAP1.1:text/xml; charset=utf-8;
SOAP1.2: application/soap+xml; charset=utf-8
命名空間不一樣:
SOAP1.1:http://schemas.xmlsoap.org/soap/envelope/
SOAP1.2:http://www.w3.org/2003/05/soap-envelope
UDDI:就是一個目錄服務,提供搜索和註冊功能,由於不經常使用,因此瞭解下就能夠了。
公網服務地址:http://www.webxml.com.cn/zh_cn/index.aspx
進入該網站後,--> 點擊 WEB服務 --> 點擊 所須要的WSDL連接
wsimport命令介紹
wimport就是jdk提供的的一個工具,它的做用是:根據WSDL地址生成客戶端代碼。
wimport位置:D:\learn\Java\JDK\jdk1.8.0_161\bin
wsimport經常使用的參數:
-d,生成.class文件的,默認的參數。
-s,生成.java文件的。
-p,指定包名的,若是不加該參數,默認包名就是wsdl文檔中的命名空間的倒序。
wsimport僅支持SOAP1.1客戶端的生成。
調用公網手機號歸屬地查詢服務
第一步:在對應的src目錄下,使用wsimport命令生成客戶端代碼
wsimport -p com.itheima.mobile -s . http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl
package com.itheima.mobile.client;
import com.itheima.mobile.MobileCodeWS;
import com.itheima.mobile.MobileCodeWSSoap;
/*
* 公網手機號查詢客戶端
*/
public class MobileClient {
public static void main(String[] args) {
// 建立服務視圖
MobileCodeWS mobileCodeWS = new MobileCodeWS();
// 獲取服務實現類
MobileCodeWSSoap mobileCodeWSSoap = mobileCodeWS.getPort(MobileCodeWSSoap.class);
// 調用查詢方法
String reuslt = mobileCodeWSSoap.getMobileCodeInfo("1365131", null);
System.out.println(reuslt);
}
}
效果截圖以下所示:
調用公網天氣服務端查詢
方法同上 調用公網手機號歸屬地查詢服務
第一步:在對應的src目錄下,使用wsimport命令生成客戶端代碼
wsimport -p com.itheima.weather -s . http://ws.webxml.com.cn/WebServices/WeatherWS.asmx?wsdl
可是此時會出現一個錯誤,以下圖所示:
WeatherWS.xml
另存下來,而後刪除掉標籤:
<s:element ref="s:schema" />
,而後保存,再次使用wsimport命令生成客戶端代碼,此時不會再報錯了
package com.itheima.weather.client;
import java.util.List;
import com.itheima.weather.ArrayOfString;
import com.itheima.weather.WeatherWS;
import com.itheima.weather.WeatherWSSoap;
public class WeatherClient {
public static void main(String[] args) {
// 建立服務視圖
WeatherWS weatherWS = new WeatherWS();
// 獲取服務實現類
WeatherWSSoap weatherWSSoap = weatherWS.getPort(WeatherWSSoap.class);
// 調用查詢方法
ArrayOfString arrayOfString = weatherWSSoap.getWeather("北京", "");
List<String> list = arrayOfString.getString();
for (String str : list) {
System.out.println(str);
}
}
}
效果截圖以下所示:
第一種生成客戶端調用方式特色:
該種方式使用簡單,但一些關鍵的元素在代碼生成時寫死到生成代碼中,不方便維護,因此僅用於測試。
即:service編程調用方式
package com.itheima.mobile.client;
import java.io.IOException;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import com.itheima.mobile.MobileCodeWSSoap;
/*
* service編程實現服務端調用
*/
public class ServiceClient {
public static void main(String[] args) throws IOException {
// 建立WSDL的URL,注意:不是服務地址
URL url = new URL("http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl");
// 建立服務名稱,參數解釋:一、namespaceURI 命名空間地址 二、localPart 服務視圖名稱
QName qname = new QName("http://WebXml.com.cn/", "MobileCodeWS");
// 建立服務視圖,參數解釋:一、wsdlDocumentLocation WSDL地址 二、serviceName 服務名稱
Service service = Service.create(url, qname);
// 獲取服務實現類
MobileCodeWSSoap mobileCodeWSSoap = service.getPort(MobileCodeWSSoap.class);
// 調用查詢方法
String reuslt = mobileCodeWSSoap.getMobileCodeInfo("13651311090", "");
System.out.println(reuslt);
}
}
第二種生成客戶端調用方式特色:
該種方式能夠自定義關鍵元素,方便之後維護,是一種標準的開發方式。
即:模擬客戶端方式
開發步驟:
第一步:建立服務地址
第二步:打開一個通向服務地址的鏈接
第三步:設置參數
設置POST,POST必須大寫,若是不大寫,報以下異常:
package com.itheima.mobile.client;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
/*
* HttpURLConnection調用方式實現服務端調用
*/
public class HttpClient {
public static void main(String[] args) throws IOException {
// 第一步:建立服務地址,注意:不是WSDL地址
URL url = new URL("http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx");
// 第二步:打開一個通向服務地址的鏈接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// 第三步:設置參數
// 設置POST,POST必須大寫,若是不大寫,報以下異常:
// 3.一、設置發送方式:POST必須大寫
connection.setRequestMethod("POST");
// 3.二、設置數據格式:content-type
connection.setRequestProperty("content-type", "text/xml;charset=utf-8");
// 3.三、設置輸入輸出:由於默認新建立的connection沒有讀寫權限
connection.setDoInput(true);
connection.setDoOutput(true);
// 若是不設置輸入輸出,會報以下異常:
// 第四步:組織SOAP數據,發送請求
String soapXML = getXML("13651311090");
OutputStream os = connection.getOutputStream();
os.write(soapXML.getBytes());
// 第五步:接收服務端響應,打印
int responseCode = connection.getResponseCode();
if (200 == responseCode) { // 表示服務端響應成功
InputStream is = connection.getInputStream();
InputStreamReader isr = new InputStreamReader(is); // 因爲字節流容易出現亂碼,因此把字節流轉換爲字符流
BufferedReader br = new BufferedReader(isr); // 爲了高效,裝飾一把,裝飾設計模式
StringBuilder sb = new StringBuilder();
String temp = null;
while (null != (temp = br.readLine())) {
sb.append(temp);
}
System.out.println(sb.toString());
// 從裏往外關流
is.close();
isr.close();
br.close();
}
os.close();
}
public static String getXML(String phoneNum) {
String soapXML = "<?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>" + phoneNum + "</mobileCode>"
+ "<userID></userID>"
+ "</getMobileCodeInfo>"
+ "</soap:Body>"
+ "</soap:Envelope>";
return soapXML;
}
}
示例代碼以下:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript">
function queryMobile() {
// 建立XMLHttpRequest對象
var xhr = new XMLHttpRequest();
// 打開鏈接
xhr.open("post", "http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx", true);
// 設置數據類型
xhr.setRequestHeader("content-type", "text/xml;charset=utf-8");
// 設置回調函數
xhr.onreadystatechange=function() {
// 判斷是否發送成功和判斷服務端是否響應成功
if (4 == xhr.readyState && 200 == xhr.status) {
alert(xhr.responseText);
}
}
// 組織SOAP協議數據
var soapXML = "<?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>" + document.getElementById("phoneNum").value + "</mobileCode>"
+ "<userID></userID>"
+ "</getMobileCodeInfo>"
+ "</soap:Body>"
+ "</soap:Envelope>";
alert(soapXML);
// 發送數據
xhr.send(soapXML);
}
</script>
</head>
<body>
手機號查詢:<input type="text" id="phoneNum"/>
<input type="button" value="查詢" onclick="javascript:queryMobile();"/>
</body>
</html>
詳解以下:
WebService的註解都位於javax.jws包下:
@WebService-定義服務,在public class 上邊
targetNamespace:指定命名空間
name:portType的名稱
portName:port的名稱
serviceName:服務名稱
endpointInterface:SEI接口地址,若是一個服務類實現了多個接口,只須要發佈一個接口的方法,可經過此註解指定要發佈服務的接口。
@WebMethod-定義方法,在公開方法上邊
operationName:方法名
exclude:設置爲true表示此方法不是webservice方法,不發佈它;反之則表示webservice方法,默認是false
@WebResult-定義返回值,在方法返回值前邊
name:返回結果值的名稱
@WebParam-定義參數,在方法參數前邊
name:指定參數的名稱
做用:
經過註解,能夠更加形像的描述Web服務。對自動生成的wsdl文檔進行修改,爲使用者提供一個更加清晰的wsdl文檔。
當修改了WebService註解以後,會影響客戶端生成的代碼。調用的方法名和參數名也發生了變化。
示例代碼以下:
package com.itheima.webservice.jaxws.ws;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.ws.BindingType;
import javax.xml.ws.soap.SOAPBinding;
@WebService(
targetNamespace="http://service.cn.itcast",
name="WeatherWSSoap",
portName="WeatherWSSoapPort",
serviceName="WeatherWS"
) // @WebService表示該類是一個服務類,須要發佈其中的public的方法
// @BindingType(SOAPBinding.SOAP12HTTP_BINDING)
public class WeatherInterfaceImpl implements WeatherInterface {
@WebMethod(
operationName="getWeather",
exclude=false
)
@Override
public @WebResult(name="result")String queryWeather(@WebParam(name="cityName")String cityName) {
System.out.println("from client..." + cityName);
String weather = "晴";
return weather; }}