l Web service 即web服務,它是一種跨編程語言和跨操做系統平臺的遠程調用技術即跨平臺遠程調用技術。java
l 採用標準SOAP(Simple Object Access Protocol) 協議傳輸,soap屬於w3c標準。Soap協議是基於http的應用層協議,soap協議傳輸是xml數據。c++
l 採用wsdl做爲描述語言即webservice使用說明書,wsdl屬w3c標準。web
l xml是webservice的跨平臺的基礎,XML主要的優勢在於它既與平臺無關,又與廠商無關。spring
l XSD,W3C爲webservice制定了一套傳輸數據類型,使用xml進行描述,即XSD(XML Schema Datatypes),任何編程語言寫的webservice接口在發送數據時都要轉換成webservice標準的XSD發送。apache
l 當前非SOAP協議的webService以輕量爲首要目標,好比http rest方式也是webservice的一種方式,或者直接使用http自定義數據協議,好比http傳輸json數據,http傳輸xml數據等。編程
SOAP即簡單對象訪問協議(Simple Object Access Protocal) 是一種簡單的基於 XML 的協議,它使應用程序經過 HTTP 來交換信息,簡單理解爲soap=http+xml。json
Soap協議版本主要使用soap1.1、soap1.2。安全
SOAP不是webservice的專有協議,其餘應用協議也使用soap傳輸數據。例如,SMTP、tr069等。服務器
WSDL 是基於 XML 的用於描述Web Service及其函數、參數和返回值。通俗理解Wsdl是webservice的使用說明書。網絡
UDDI 是一種目錄服務,經過它,企業可註冊並搜索 Web services。企業將本身提供的Web Service註冊在UDDI,也可使用別的企業在UDDI註冊的web service服務,從而達到資源共享。UDDI旨在將全球的webservcie資源進行共享,促進全球經濟合做。
UDDI現狀:
目前大部分企業使用webservice並非必須使用UDDI,由於用戶經過WSDL知道了web service的地址,能夠直接經過WSDL調用webservice。
JAVA 中共有三種WebService 規範,分別是JAX-WS(JAX-RPC)、JAXM&SAAJ、JAX-RS。
下面來分別簡要的介紹一下這三個規範。
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(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 是JAVA 針對REST(Representation State Transfer)風格制定的一套Web 服務規範,因爲推出的較晚,該規範(JSR 311,目前JAX-RS 的版本爲1.0)並未隨JDK1.6 一塊兒發行。
1. 編寫SEI(Service Endpoint Interface),SEI在webservice中稱爲portType,在java中稱爲接口。
代碼以下:
/**
* 天氣查詢服務接口
* @author 傳智播客 Java學院
* @version V1.0
*/
public interface WeatherInterface {
//天氣查詢
public String queryWeather(String cityName);
}
2. 編寫SEI實現類,此類做爲webservice提供服務類
代碼以下:
/**
* 天氣查詢服務接口實現類
* @author 傳智播客 Java學院
* @version V1.0
*/
@WebService
public class WeatherInterfaceImpl implements WeatherInterface {
@Override
public String queryWeather(String cityName) {
System.out.println("from client.."+cityName);
String result = "晴朗";
System.out.println("to client..."+result);
return result;
}
public static void main(String[] args) {
//發送webservice服務
Endpoint.publish("http://192.168.1.100:1234/weather", new WeatherInterfaceImpl());
}
}
注意:
SEI實現類中至少要有一個非靜態的公開方法須要做爲webservice服務方法。
public class 上邊要加上@WebService
3. endpoint發佈服務
//發送webservice服務
Endpoint.publish("http://192.168.1.100:1234/weather", new WeatherInterfaceImpl());
Webservice發佈成功,經過wsdl查看webservice發佈的正確性
1. 在地址欄輸入(注意後面的參數?wsdl)
http://192.168.1.100:1234/weather?wsdl
2. Wsdl不是webService,只是獲取一個用於描述WebService的說明文件
3. wsdl- WebServiceDescriptionLanguage,是以XML文件形式來描述WebService的」說明書」,有了說明書,咱們才能夠知道如何使用或是調用這個服務.
wsimport是jdk自帶的webservice客戶端工具,能夠根據wsdl文檔生成客戶端調用代碼(java代碼).固然,不管服務器端的WebService是用什麼語言寫的,均可以生成調用webservice的客戶端代碼,服務端經過客戶端代碼調用webservice。
wsimport.exe位於JAVA_HOME\bin目錄下.
經常使用參數爲:
-d<目錄> - 將生成.class文件。默認參數。
-s<目錄> - 將生成.java文件。
-p<生成的新包名> -將生成的類,放於指定的包下。
(wsdlurl) - http://server:port/service?wsdl,必須的參數。
示例:
C:/> wsimport –s . http://127.0.0.1:1234/weather?wsdl
注意:-s不能分開,-s後面有個小點
1. 能夠經過java –version檢查你當前的版本號保存是jdk1.6以上。Jdk1.6.0_13之後的版本支持jaxws2.1。
2. 在Eclipse中建立一個空的java工程爲wsimport,此工程做爲存放客戶端代碼。
3. cmd命令行進入此wsimport 工程的src目錄,
輸入如下命令:
參數說明:-s是指編譯出源代碼文件,後面的.(點)指將代碼放到當前目錄下.
最後面的http….是指獲取wsdl說明書的地址.
4. 生成完成,刷新Eclipse中wsimport工程,將src下生成.java文件代碼Copy到webservice客戶端工程(見下)中。
代碼以下:
/**
* 天氣查詢客戶端
* @author 傳智播客 Java學院
* @version V1.0
*/
public class WeatherClient {
public static void main(String[] args) {
//建立服務視圖
WeatherInterfaceImplService weatherInterfaceImplService =new WeatherInterfaceImplService();
//經過服務視圖獲得服務端點
WeatherInterfaceImpl weatherInterfaceImpl= weatherInterfaceImplService.getPort(WeatherInterfaceImpl.class);
//調用webservice服務方法
String result = weatherInterfaceImpl.queryWeather("鄭州");
System.out.println(result);
}
}
1、採用xml支持跨平臺遠程調用。
2、基於http的soap協議,可跨越防火牆。
3、支持面向對象開發。
4、有利於軟件和數據重用,實現鬆耦合。
因爲soap是基於xml傳輸,自己使用xml傳輸會傳輸一些無關的東西從而效率不高,隨着soap協議的完善,soap協議增長了許多內容,這樣就致使了使用soap協議進行數據傳輸的效率不高。
用於軟件集成和複用
適用:
l 用於接口服務,不考慮客戶端類型,不考慮性能,建議使用
Ø 用於公開接口服務
面向互聯網公開的接口,例如:某公司產品促銷介紹、股票信息查詢等,由於webservice使用的soap協議是一個標準協議,其它公司使用標準協議通訊,方便系統開發和維護。好比:便民網站的天氣查詢接口、火車時刻查詢接口等。
Ø 用於內部接口服務
一個大的系統平臺是由若干個系統組成,系統與系統之間存在數據訪問需求,爲了減小系統與系統之間的耦合性能夠將接口抽取出來提供單獨的接口服務供它系統調用,以下圖是企業ERP系統的接口服務圖:
l 服務端已經肯定使用webservice,客戶端沒法選擇,只能使用webservice
不適用:
l 對性能要求很高的應用,不建議使用webservice
好比銀行交易系統、股票交易系統等,任何延遲均可能形成沒法估量的損失。
l 同構程序之間通訊不建議使用webservice
好比Java的RMI一樣能夠實現遠程調用,並且性能比webservice好不少。
WSDL 指網絡服務描述語言(Web Services Description Language)。
WSDL是一種使用 XML 編寫的文檔。這種文檔可描述某個 Web service。它可規定服務的位置,以及此服務提供的操做(或方法)。
WSDL 是一種 XML 文檔
WSDL 用於描述網絡服務
WSDL 也可用於定位網絡服務
<service> 服務視圖,webservice的服務結點,它包括了服務端點
<binding> 爲每一個服務端點定義消息格式和協議細節
<portType> 服務端點,描述 web service可被執行的操做方法,以及相關的消息,經過binding指向portType
<message> 定義一個操做(方法)的數據參數(可有多個參數)
<types> 定義 web service 使用的所有數據類型
從下往上讀
先找到服務視圖,經過binging找到protType,找到了protType就找到了咱們要調用的webservice方法。
查看wsdl說明要從下往上看:
1服務視圖(根)
2經過服務視圖,bingding到porttype
3、調用portType的方法
第一步:閱讀wsdl,搞清楚服務視圖 service、 協議格式binding 服務端點porttype
第二步:建立服務視圖
第三步:建立服務端點
第四步:經過服務端點調用服務方法
第一步:找到天氣查詢的webservice WSDL文件拷貝到D盤根目錄
第二步:根據WSDL生成客戶端調用類,使用wsimport生成
Wsimport –s . file:///d:\WeatherWebService.wsdl
第三步:將生成的代碼拷貝至工程中
第四步:編寫客戶端調用代碼
/**
* 互聯網天氣查詢客戶端
* @author 傳智播客 Java學院
* @version V1.0
*/
public class WebWeatherClient {
public static void main(String[] args) {
//建立服務視圖
WeatherWebService weatherWebService = new WeatherWebService();
//經過服務視圖獲得服務端點
WeatherWebServiceSoap weatherWebServiceSoap =weatherWebService.getWeatherWebServiceSoap();
//調用webservice服務方法
ArrayOfString arrayOfString = weatherWebServiceSoap.getWeatherbyCityName("鄭州");
List<String> resultlist = arrayOfString.getString();
//查詢天氣查詢結果
for(String result:resultlist){
System.out.println(result);
}
}
}
第一步:建立URL,指定資源地址即wsdl地址
第二步:建立Qname,指定命名空間和視圖名稱
第三步:建立服務視圖對象service
第四步:從服務視圖中獲得服務端點即服務接口(這裏須要服務接口類型,可以使用wsimport生成後只留下porttype)
第五步:經過服務端點調用服務方法
/**
* 使用javax.xml.ws.Service調用webservice服務
* @author 傳智播客 Java學院
* @version V1.0
*/
public class WeatherClient2 {
public static void main(String[] args) throws MalformedURLException {
//定義url,參數爲wsdl地址
URL url = new URL("http://192.168.1.100:1234/weather?wsdl");
//定義qname,第一個參數是命名空間,第二個參數名稱是wsdl裏邊的服務名
QName qName = new QName("http://impl.sei.jaxws.ws.itcast.cn/", "WeatherInterfaceImplService");
//建立服務視圖
Service service = Service.create(url, qName);
//經過服務視圖獲得服務端點
WeatherInterfaceImpl weatherInterfaceImpl =service.getPort(WeatherInterfaceImpl.class);
//調用webservice
System.out.println(weatherInterfaceImpl.queryWeather("鄭州"));
}
}
/**
* 使用javax.xml.ws.Service調用公網webservice服務
* @author 傳智播客 Java學院
* @version V1.0
*/
public class WebWeatherClient2 {
public static void main(String[] args) throws MalformedURLException {
//定義url,參數爲wsdl地址
URL url = new URL("file:/D:/WeatherWebService.wsdl");
//定義qname,第一個參數是命名空間,第二個參數名稱是wsdl裏邊的服務名
QName qName = new QName("http://WebXml.com.cn/", "WeatherWebService");
//建立服務視圖
Service service = Service.create(url, qName);
//經過服務視圖獲得服務端點
WeatherWebServiceSoap weatherWebServiceSoap =service.getPort(WeatherWebServiceSoap.class);
//調用webservice
ArrayOfString arrayOfString = weatherWebServiceSoap.getWeatherbyCityName("鄭州");
List<String> resultlist = arrayOfString.getString();
//查詢天氣查詢結果
for(String result:resultlist){
System.out.println(result);
}
}
}
/**
* 使用service類調用公網手機號歸屬地查詢服務
*/
public class MobileClient_Service {
public static void main(String[] args) throws MalformedURLException {
//wsdl的url
URL url = new URL("http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx");
//定義servicename
QName serviceName = new QName("http://WebXml.com.cn/", "MobileCodeWS");
//獲得 服務視圖
Service service = Service.create(url, serviceName);
//獲得portType
MobileCodeWSSoap mobileCodeWSSoap = service.getPort(MobileCodeWSSoap.class);
//設備portType的方法
String resultString = mobileCodeWSSoap.getMobileCodeInfo("1863819", "");
//查詢數據
System.out.println(resultString);
}
}
Wsimport生成代碼調用webservice沒法指定webservice的地址,使用生成的服務視圖類獲取服務端點(postType)實例。
Service調用Webservice能夠指定webservice的地址,只須要服務端點的接口便可獲取服務端點實例。
SOAP 是一種網絡通訊協議
SOAP即Simple Object Access Protocol簡易對象訪問協議
SOAP 用於跨平臺應用程序之間的通訊
SOAP 被設計用來經過因特網(http)進行通訊
SOAP = HTTP+XML,其實就是經過HTTP發xml數據
SOAP 很簡單並可擴展支持面向對象
SOAP 容許您跨越防火牆
SOAP 將被做爲 W3C 標準來發展
使用TCP/IP Monitor能夠監視tcp/ip協議的報文內容,因爲http是基於Tcp的應用協議,而webservice是基於http實現,因此經過tcp/ip monitor能夠監視webservice請求及響應的內容。
//定義url,參數爲wsdl地址
URL url = new URL("http://127.0.0.1:54321/weather?wsdl");
//定義qname,第一個參數是命名空間,第二個參數名稱是wsdl裏邊的服務名
QName qName = new QName("http://server.jaxws.webservice.itcast.cn/", "WeatherInterfaceImplService");
//建立服務視圖
Service service = Service.create(url, qName);
//經過服務視圖獲得服務端點
WeatherInterfaceImpl weatherInterfaceImpl =service.getPort(WeatherInterfaceImpl.class);
//調用webservice
System.out.println(weatherInterfaceImpl.queryWeather("鄭州"));
注意紅色標註:
POST /weather HTTP/1.1
Accept: text/xml, multipart/related
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://server.jaxws.ws.itcast.cn/WeatherServer/queryWeatherRequest"
User-Agent: JAX-WS RI 2.2.8 svn-revision#13980
Host: 127.0.0.1:4321
Connection: keep-alive
Content-Length: 232
<?xml version='1.0' encoding='UTF-8'?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:queryWeather xmlns:ns2="http://server.jaxws.ws.itcast.cn/">
<arg0>鄭州</arg0>
</ns2:queryWeather>
</S:Body>
</S:Envelope>
注意紅色標註:
HTTP/1.1 200 OK
Transfer-encoding: chunked
Content-type: text/xml; charset=utf-8
<?xml version='1.0' encoding='UTF-8'?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:queryWeatherResponse xmlns:ns2="http://server.jaxws.ws.itcast.cn/">
<return>天氣晴朗</return>
</ns2:queryWeatherResponse>
</S:Body>
</S:Envelope>
必需有 Envelope 元素,此元素將整個 XML 文檔標識爲一條 SOAP 消息
可選的 Header 元素,包含頭部信息
必需有Body 元素,包含全部的調用和響應信息
可選的 Fault 元素,提供有關在處理此消息所發生錯誤的信息
<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
<soap:Header>
... ...
</soap:Header>
<soap:Body>
... ...
<soap:Fault>
... ...
</soap:Fault>
</soap:Body>
</soap:Envelope>
webservice使用soap協議傳輸數據,soap是基於http的應用協議,可使用http發送soap協議數據完成webservice的請求。
本例子解析響應的xml數據使用dom4j。
/**
* 經過http發送soap協議請求webservice
* @author 傳智播客 Java學院
* @version V1.0
*/
public class HttpRequestSoap {
public static void main(String[] args) throws IOException {
//webservice地址
String webservice_url = "http://127.0.0.1:1234/weather";
//發送的soap協議內容
String soap_xml = soap_xml("鄭州");
System.out.println(soap_xml);
//建立url
URL url = new URL(webservice_url);
//建立http連接對象
HttpURLConnection httpURLConnection = (HttpURLConnection)url.openConnection();
//設置請求方法
httpURLConnection.setRequestMethod("POST");
//設置Content-type
httpURLConnection.setRequestProperty("Content-type", "text/xml;charset=\"utf-8\"");
//使用http進行輸出
httpURLConnection.setDoOutput(true);
//使用http進行輸入
httpURLConnection.setDoInput(true);
//經過輸出流發送數據
OutputStream outputStream = httpURLConnection.getOutputStream();
outputStream.write(soap_xml.getBytes());
outputStream.close();
//接收服務端響應數據
InputStream inputStream = httpURLConnection.getInputStream();
//使用buffer存在讀取的數據
byte[] buffer = new byte[1024];
//使用字節輸出流存儲讀取的數據
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
while(true){
int len = inputStream.read(buffer);
//若是流水讀取完則退出循環
if(len == -1){
break;
}
byteArrayOutputStream.write(buffer,0,len);
}
//獲得響應數據
String response_string = byteArrayOutputStream.toString();
System.out.println(response_string);
parseXml(response_string);
}
//soap協議內容
public static String soap_xml(String cityName){
String soap_xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+ "<S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\">"
+ "<S:Body>"
+ "<ns2:queryWeather xmlns:ns2=\"http://impl.sei.jaxws.ws.itcast.cn/\">"
+ "<arg0>"+ cityName + "</arg0>"
+ "</ns2:queryWeather>"
+ "</S:Body>"
+ "</S:Envelope>";
return soap_xml;
}
//解析響應的xml
public static String parseXml(String xmlString){
String result = null;
try {
Document document = DocumentHelper.parseText(xmlString);
//建立xpath解析對象
DefaultXPath defaultXPath = new DefaultXPath("//ns2:queryWeatherResponse");
//指定命名空間
defaultXPath.setNamespaceURIs(Collections.singletonMap("ns2", "http:// impl.sei.jaxws.ws.itcast.cn/"));
List<Element> elements= defaultXPath.selectNodes(document);
Element response = elements.get(0);
List<Element> results = response.selectNodes("return");
System.out.println(results.get(0).getText());
} catch (DocumentException e) {
e.printStackTrace();
}
return result;
}
}
Jaxws實現soap1.2須要加入jaxws擴展包,從sun下載jaxws-ri-2.2.8,解壓jaxws-ri-2.2.8並將lib下的jar包加載到java工程中。
在SEI實現類上添加以下註解
@BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
注意紅色標註:
POST /weather HTTP/1.1
Accept: application/soap+xml, multipart/related
Content-Type: application/soap+xml; charset=utf-8;action="http://server.jaxws.ws.itcast.cn/WeatherServer/queryWeatherRequest"
User-Agent: JAX-WS RI 2.2.8 svn-revision#13980
Host: 127.0.0.1:4321
Connection: keep-alive
Content-Length: 230
<?xml version='1.0' encoding='UTF-8'?>
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope">
<S:Body>
<ns2:queryWeather xmlns:ns2="http://server.jaxws.ws.itcast.cn/">
<arg0>鄭州</arg0>
</ns2:queryWeather>
</S:Body>
</S:Envelope>
注意紅色標註:
HTTP/1.1 200 OK
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://server.jaxws.ws.itcast.cn/">
<return>天氣晴朗</return>
</ns2:queryWeatherResponse>
</S:Body>
</S:Envelope>
相同之處:
soap1.1和soap1.2都是使用post方法
都包括Envelope和body
內容類型context-type不一樣:
soap1.1使用text/xml
soap1.2使用application/soap+xml
命名空間Envelope xmlns不一樣:
soap1.1使用http://schemas.xmlsoap.org/soap/envelope/
soap1.2使用http://www.w3.org/2003/05/soap-envelope
WebService的註解都位於javax.jws包下:
@WebService-定義服務,在public class上邊
targetNamespace:指定命名空間
name:portType的名稱
portName:port的名稱
serviceName:服務名稱
endpointInterface:SEI接口地址,若是一個服務類實現了多個接口,只須要發佈一個接口的方法,可經過此註解指定要發佈服務的接口。
@WebMethod-定義方法,在公開方法上邊
operationName:方法名
exclude:設置爲true表示此方法不是webservice方法,反之則表示webservice方法
@WebResult-定義返回值,在方法返回值前邊
name:返回結果值的名稱
@WebParam-定義參數,在方法參數前邊
name:指定參數的名稱
做用:
經過註解,能夠更加形像的描述Web服務。對自動生成的wsdl文檔進行修改,爲使用者提供一個更加清晰的wsdl文檔。
當修改了WebService註解以後,會影響客戶端生成的代碼。調用的方法名和參數名也發生了變化
/**
* 天氣查詢服務接口實現類
* @author 傳智播客 Java學院
* @version V1.0
*/
@WebService(targetNamespace="http:// webservice.itcast.cn",
serviceName="weatherService",
portName="weatherServicePort",
name="weatherServiceInterface"
)
public class WeatherInterfaceImpl implements WeatherInterface {
@WebMethod(operationName="queryWeather")
public @WebResult(name="weatherResult")String queryWeather(
@WebParam(name="cityName")String cityName) {
System.out.println("from client.."+cityName);
String result = "晴朗";
System.out.println("to client..."+result);
return result;
}
public static void main(String[] args) {
//發送webservice服務
Endpoint.publish("http://192.168.1.100:1234/weather", new WeatherInterfaceImpl());
}
}
@WebMethod對全部非靜態的公共方法對外暴露爲服務.
對於靜態方法或非public方法是不可使用@WebMethod註解的.
對public方法可使用@WebMethod(exclude=true)定義爲非對外暴露的服務。
SOAP協議支持對象格式數據,咱們能夠將天氣查詢的結果封裝在一個查詢結果對象中,字段包括:城市、日期、天氣、溫度等信息。
服務端編寫webservice的方法和前邊同樣,最後使用endpoint發佈服務。
wsimport生成客戶端代碼。
@WebService(targetNamespace="http:// webservice.itcast.cn",
serviceName="weatherService",
portName="weatherServicePort",
name="weatherServiceInterface"
)
public class WeatherInterfaceImpl implements WeatherInterface {
@Override
public @WebResult(name="weatherResult")List<WeatherModel> queryWeather(
@WebParam(name="cityName")String cityName) throws Exception {
//構造三天的天氣結果
Calendar calendar = Calendar.getInstance();
int day = calendar.get(Calendar.DATE);
//第一天的天氣
WeatherModel weatherModel_1 = new WeatherModel();
weatherModel_1.setDate(new Date());
weatherModel_1.setDetail("晴朗");
weatherModel_1.setTemperature_max(30);
weatherModel_1.setTemperature_min(23);
//次日的天氣
WeatherModel weatherModel_2 = new WeatherModel();
calendar.set(Calendar.DATE, day+1);
weatherModel_2.setDate(calendar.getTime());
weatherModel_2.setDetail("晴轉多雲");
weatherModel_2.setTemperature_max(28);
weatherModel_2.setTemperature_min(21);
//第三天的天氣
WeatherModel weatherModel_3 = new WeatherModel();
calendar.set(Calendar.DATE, day+2);
weatherModel_3.setDate(calendar.getTime());
weatherModel_3.setDetail("多雲轉小雨");
weatherModel_3.setTemperature_max(25);
weatherModel_3.setTemperature_min(18);
List<WeatherModel> list = new ArrayList<WeatherModel>();
list.add(weatherModel_1);
list.add(weatherModel_2);
list.add(weatherModel_3);
//返回三天的天氣
return list;
}
}
public class WeatherClient {
public static void main(String[] args) throws MalformedURLException, Exception_Exception {
//wsdl的url
URL url = new URL("http://127.0.0.1:12345/weather?wsdl");
//serviceName
//第一參數是命名空間地址,第二個參數是service名稱
QName serviceName = new QName("http://server.jaxws.webservice.itcast.cn/", "WeatherInterfaceImplService");
//建立服務視圖
Service service = Service.create(url, serviceName);
//經過服務視圖獲得portType
WeatherInterfaceImpl weatherInterfaceImpl = service.getPort(WeatherInterfaceImpl.class);
//調用porttype方法
List<WeatherModel> list = weatherInterfaceImpl.queryWeather("北京");
for(WeatherModel weatherModel:list){
Date date = weatherModel.getDate().toGregorianCalendar().getTime();
System.out.println(new SimpleDateFormat("yyyy-MM-dd").format(date));
}
}
}
Apache CXF = Celtix + Xfire,開始叫 Apache CeltiXfire,後來改名爲 Apache CXF 了,如下簡稱爲 CXF。Apache CXF 是一個開源的web Services 框架,CXF 幫助您構建和開發 web Services ,它支持多種協議,好比:SOAP1.1,1,2、XML/HTTP、RESTful HTTP 或者 CORBA。
CORBA(Common Object Request Broker Architecture公共對象請求代理體系結構,早期語言使用的WS。C,c++,C#)
Cxf是基於SOA總線結構,依靠spring完成模塊的集成,實現SOA方式。
靈活的部署:能夠運行有Tomcat,Jboss,Jetty(內置),weblogic上面。
從官網下載2.7.11
JAVA_HOME,
CXF_HOME=cxf的目錄
Path = %JAVA_HOME%\bin;%CXF_HOME%\bin;
CLASSPATH=.;%CXF_HOME%\lib\cxf-manifest.jar
建立服務接口和服務類的方法同上邊章節描述,編寫SEI及SEI的實現。
注意:與jaxws編程不一樣的是將@WebService註解加在接口上邊。
使用cxf開發webservice這裏只須要在接口上加@webservice註解便可,和jaxws開發不一樣。
@WebService
@BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
public interface WeatherInterface {
//根據城市名稱查詢將來三天的天氣
public List<WeatherModel> queryWeather(String cityName) throws Exception;
}
使用cxf開發不用在接口實現類上加@webservice註解,由於cxf發佈服務時能夠指定接口。
public class WeatherInterfaceImpl implements WeatherInterface {
@Override
public List<WeatherModel> queryWeather(String cityName) throws Exception {
//構造三天的天氣結果
Calendar calendar = Calendar.getInstance();
int day = calendar.get(Calendar.DATE);
WeatherModel weatherModel_1 = new WeatherModel();
weatherModel_1.setDate(new Date());
weatherModel_1.setDetail("晴朗");
weatherModel_1.setTemperature_max(30);
weatherModel_1.setTemperature_min(23);
WeatherModel weatherModel_2 = new WeatherModel();
calendar.set(Calendar.DATE, day+1);
weatherModel_2.setDate(calendar.getTime());
weatherModel_2.setDetail("晴轉多雲");
weatherModel_2.setTemperature_max(28);
weatherModel_2.setTemperature_min(21);
WeatherModel weatherModel_3 = new WeatherModel();
calendar.set(Calendar.DATE, day+2);
weatherModel_3.setDate(calendar.getTime());
weatherModel_3.setDetail("多雲轉小雨");
weatherModel_3.setTemperature_max(25);
weatherModel_3.setTemperature_min(18);
List<WeatherModel> list = new ArrayList<WeatherModel>();
list.add(weatherModel_1);
list.add(weatherModel_2);
list.add(weatherModel_3);
return list;
}
}
package cn.itcast.ws.jaxws.server;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
/**
* CXF發佈jaxws服務類
* @author Thinkpad
*
*/
public class Server {
/**
* @param args
*/
public static void main(String[] args) {
//建立服務工廠bean
JaxWsServerFactoryBean jaxWsServerFactoryBean = new JaxWsServerFactoryBean();
//指定服務接口
jaxWsServerFactoryBean.setServiceClass(WeatherServerInterface.class);
//指定服務實現對象
jaxWsServerFactoryBean.setServiceBean(new WeatherInterfaceImpl());
//指定webservice的地址
jaxWsServerFactoryBean.setAddress("http://192.168.1.100:1234/weather");
//建立webservice服務
jaxWsServerFactoryBean.create();
}
}
咱們分別使用wsimport和wsdl2java生成客戶端代碼,均可以正常使用。
**wsdl2java能夠生成soap1.1和soap1.2
先讓咱們瞭解一下cxf的wsdl2java工具,它的功能就如同wsimport同樣,能夠生成一堆客戶端調用的代碼。
在命令行執行:
wsdl2java –d . http://192.168.1.100:1234/weather?wsdl
注意:
生成後WeatherService報錯:
緣由是cxf須要JAX-WS API 2.2而jdk6的jax-ws是2.1 版本,須要
wsdl2java 使用「-frontend jaxws21「
即以下:
wsdl2java –d . –frontend jaxws21 http://localhost:1234/weather?wsdl
package cn.itcast.ws.jaxws.client;
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import cn.itcast.ws.jaxws.server.WeatherServerInterface;
public class Client3 {
public static void main(String[] args) throws MalformedURLException {
//建立URL,資源定位
URL url = new URL("http://192.168.1.100:1234/weather?wsdl");
//Qname,肯定命名空間地址,和服務視圖名稱
QName qName = new QName("http://service.itcast.cn/", "WeatherInterfaceService");
//建立service
Service service = Service.create(url, qName);
//建立porttype(服務端點)
WeatherInterface weatherInterface = service.getPort(WeatherInterface.class);
//經過服務端點調用服務方法
weatherServerInterface.queryWather("鄭州");
}
}
//建立代碼工廠bean
JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();
//設置接口類型(portType)jaxWsProxyFactoryBean.setServiceClass(WeatherInterface.class);
//設置webservice地址jaxWsProxyFactoryBean.setAddress("http://192.168.1.100:1234/weather");
//建立portType調用實例
WeatherInterface weatherInterface =(WeatherInterface) jaxWsProxyFactoryBean.create();
//調用webservice
weatherServerInterface.queryWather("鄭州");
在服務接口的上面都添加
@BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
以下:
@WebService
@BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
public interface WeatherServerInterface
@WebService(endpointInterface = "cn.itcast.ws.jaxws.server.WeatherServerInterface")
@BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
public class WeatherServer implements WeatherServerInterface
編寫方法同上面章節描述。
@WebService(targetNamespace="http://service.itcast.cn/",
name="WeatherInterface",//porttype的名稱
portName="WeatherInterfacePort",
serviceName="WeatherInterfaceService"
)
@BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
public interface WeatherInterface {
//根據城市名稱查詢公網天氣服務接口
public List<String> queryWeather(String cityName) throws Exception;
}
需求:服務類須要調用公網天氣查詢客戶端。
public class WeatherInterfaceImpl implements WeatherInterface {
//此爲公網查詢客戶端須要經過spring配置並注入
private WeatherWebServiceSoap weatherWebServiceSoap;
@Override
public List<String> queryWeather(String cityName) throws Exception {
ArrayOfString arrayOfString = weatherWebServiceSoap.getWeatherbyCityName("鄭州");
List<String> results = arrayOfString.getString();
for(String result:results){
System.out.println(result);
}
return results;
}
public WeatherWebServiceSoap getWeatherWebServiceSoap() {
return weatherWebServiceSoap;
}
public void setWeatherWebServiceSoap(WeatherWebServiceSoap weatherWebServiceSoap) {
this.weatherWebServiceSoap = weatherWebServiceSoap;
}
}
將上邊章節生成的公網天氣查詢客戶端調用代碼考入本工程。
生成方法在此再也不贅述。
將applicationContext.xml放在WEB-INF下
內容以下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:cxf="http://cxf.apache.org/core"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd">
<!-- 配置發佈webservice服務 -->
<jaxws:server address="/weather" serviceClass="cn.itcast.webservice.jaxws.server.WeatherInterface">
<jaxws:serviceBean>
<ref bean="weatherInterface"/>
</jaxws:serviceBean>
</jaxws:server>
<!-- 公網天氣查詢客戶端 -->
<jaxws:client id="weatherClient" serviceClass="cn.com.webxml.WeatherWebServiceSoap" address="http://www.webxml.com.cn/WebServices/WeatherWebService.asmx" />
<!-- 本系統對外服務的天氣查詢service -->
<bean id="weatherInterface" class="cn.itcast.webservice.jaxws.server.WeatherInterfaceImpl" >
<property name="weatherWebServiceSoap" ref="weatherClient" />
</bean>
</beans>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class> org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>cxf</servlet-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>cxf</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
訪問:http://192.168.1.100:8080/.../ws/weather?wsdl
客戶端建立同前邊章節,此處再也不贅述。
REST 是一種軟件架構模式,只是一種風格,rest服務採用HTTP 作傳輸協議,REST 對於HTTP 的利用實現精確的資源定位。
Rest要求對資源定位更加準確,以下:
非rest方式:http://ip:port/queryUser.action?userType=student&id=001
Rest方式:http://ip:port/user/student/query/001
Rest方式表示互聯網上的資源更加準確,可是也有缺點,可能目錄的層級較多不容易理解。
REST 是一種軟件架構理念,如今被移植到Web 服務上,那麼在開發Web 服務上,偏於面向資源的服務適用於REST,REST 簡單易用,效率高,SOAP 成熟度較高,安全性較好。
注意:REST 不等於WebService,JAX-RS 只是將REST 設計風格應用到Web 服務開發上。
發佈查詢學生信息的服務,以json和xml數據格式返回。
@XmlRootElement(name="student")
public class Student {
private long id;
private String name;
private Date birthday;
@WebService
@Path("/student")
public interface StudentService {
@GET
@Produces(MediaType.APPLICATION_XML)
@Path("/query/{id}")
public Student queryStudent(@PathParam("id")long id)throws Exception;
@GET
@Produces({"application/json;charset=utf-8",MediaType.APPLICATION_XML})
@Path("/querylist/{id}")
public List<Student> queryStudentList(@PathParam("id")long id)throws Exception;
}
上邊代碼中:
queryStudent方法以xml格式發佈
queryStudentList方法以json和xml兩種格式發佈。
public class StudentServiceImpl implements StudentService {
@Override
public Student queryStudent(long id) throws Exception {
Student student = new Student();
student.setId(100000l);
student.setName("張三");
student.setBirthday(new Date());
return student;
}
@Override
public List<Student> queryStudentList(long id) throws Exception {
Student student1 = new Student();
student1.setId(100000l);
student1.setName("李四");
student1.setBirthday(new Date());
Student student2 = new Student();
student2.setId(100000l);
student2.setName("張三");
student2.setBirthday(new Date());
List<Student> list = new ArrayList<Student>();
list.add(student1);
list.add(student2);
return list;
}
}
public class RestServer {
public static void main(String[] args) {
JAXRSServerFactoryBean jaxrsServerFactoryBean = new JAXRSServerFactoryBean();
//rest地址
jaxrsServerFactoryBean.setAddress("http://127.0.0.1:12345/rest");
//設置SEI實現類
jaxrsServerFactoryBean.setResourceClasses(StudentServiceImpl.class);
jaxrsServerFactoryBean.create();
}
}
<!-- rest服務發佈 -->
<jaxrs:server address="/rest">
<jaxrs:serviceBeans>
<ref bean="studentService"/>
</jaxrs:serviceBeans>
</jaxrs:server>
<!-- 學生查詢,rest方式 -->
<bean id="studentService" class="cn.itcast.ws.cxf.rest.server.StudentServiceImpl">
</bean>
queryStudent方法測試:
http://127.0.0.1:8080/工程名/ws/rest/student/query/1
queryStudentList方法測試:
返回json
http://127.0.0.1:8080/工程名/ws/rest/student/querylist/1?_type=json
返回xml
http://127.0.0.1:8080/工程名/ws/rest/student/querylist/1?_type=xml
使用springmvc+CXF實現便民網站,同時對外提供webservice服務。
調用公網的webservice,
將本身的服務發佈成webservice。
參考cxf下的lib目錄
Cxf2.7.11默認和spring3.0.7整合,這裏咱們使用spring3.1.4,將cxf中的spring開頭的jar去掉,拷貝spring及springmvc的全部jar包。
@WebService(targetNamespace="http://service.itcast.cn/",
name="WeatherInterface",//porttype的名稱
portName="WeatherInterfacePort",
serviceName="WeatherInterfaceService"
)
public interface WeatherService {
//根據城市名稱查詢三天的天氣
public List<WeatherModel> queryWeather(String cityName) throws Exception;
}
public class WeatherServiceImpl implements WeatherService {
@Resource
private WeatherWebServiceSoap weatherWebServiceSoap;
@Override
public List<WeatherModel> queryWeather(String cityName) throws Exception {
//調用dao獲取天氣信息
ArrayOfString arrayOfString = weatherWebServiceSoap.getWeatherbyCityName(cityName);
List<String> list = arrayOfString.getString();
for(String result:list){
System.out.println(result);
}
//解析獲取的天氣信息
WeatherModel weatherModel_1 = new WeatherModel();
weatherModel_1.setDetail(list.get(6));//天氣概況
weatherModel_1.setImg(list.get(8));//圖標
WeatherModel weatherModel_2 = new WeatherModel();
weatherModel_2.setDetail(list.get(13));//天氣概況
weatherModel_2.setImg(list.get(15));//圖標
WeatherModel weatherModel_3 = new WeatherModel();
weatherModel_3.setDetail(list.get(18));//天氣概況
weatherModel_3.setImg(list.get(20));//圖標
//返回的結果集
List<WeatherModel> list_l = new ArrayList<WeatherModel>();
list_l.add(weatherModel_1);
list_l.add(weatherModel_2);
list_l.add(weatherModel_3);
return list_l;
}
}
將上邊章節生成的公網天氣查詢客戶端調用代碼考入本工程。
生成方法在此再也不贅述。
將上邊編寫的天氣查詢服務接口在spring環境配置。
Classpath 下添加applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/jaxrs
http://cxf.apache.org/schemas/jaxrs.xsd">
<!-- 導入資源文件 -->
<beanclass="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:config.properties</value>
</list>
</property>
</bean>
<!-- 配置發佈webservice服務 -->
<jaxws:server address="/weather"
serviceClass="cn.itcast.weather.service.WeatherService">
<jaxws:serviceBean>
<ref bean="weatherService" />
</jaxws:serviceBean>
</jaxws:server>
<!-- 天氣查詢的bean -->
<bean id="weatherService" class="cn.itcast.weather.service.impl.WeatherServiceImpl">
</bean>
<!-- 公網天氣查詢客戶端 -->
<jaxws:client id="weatherWebServiceSoap" serviceClass="cn.com.webxml.WeatherWebServiceSoap"
address="${webservice_url_weather}" />
</beans>
config.properties
//公網天氣查詢地址
webservice_url_weather=http://www.webxml.com.cn/WebServices/WeatherWebService.asmx
實現用戶進入天氣查詢頁面,輸入城市查詢天氣。
控制層調用天氣查詢服務接口。
package cn.itcast.ws.cxf.servlet;
import java.io.IOException;
import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
import org.springframework.context.ApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils;
import cn.itcast.ws.cxf.mobile.service.MobileService;
public class MobileServlet extends HttpServlet {
private MobileService mobileService;
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{ String code = request.getParameter("code"); ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext()); mobileService = (MobileService) context.getBean("mobileService"); if(null != code && !"".equals(code)){ String result = mobileService.queryMobile(code); request.setAttribute("result", result); } request.getRequestDispatcher("WEB-INF/jsp/queryMobile.jsp").forward(request, response); }
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{ String code = request.getParameter("code"); ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext()); mobileService = (MobileService) context.getBean("mobileService"); if(null != code && !"".equals(code)){ String result = mobileService.queryMobile(code); request.setAttribute("result", result); } request.getRequestDispatcher("WEB-INF/jsp/queryMobile.jsp").forward(request, response); } }
|
Web.xml中作如下配置:
啓動系統加載spring環境
springmvc的servlet
CXF的servlet
<!-- spring配置文件 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/applicationContext.xml</param-value>
</context-param>
<!-- 啓動加載spring -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- CXF的servlet -->
<servlet>
<description>Apache CXF Endpoint</description>
<display-name>cxf</display-name>
<servlet-name>cxf</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>cxf</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
<!-- mobileServlet配置 -->
<servlet>
<servlet-name>mobileServlet</servlet-name>
<servlet-class> cn.itcast.ws.cxf.servlet.MobileServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name> mobileServlet</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
<!-- post提交亂碼處理 -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>