WebService就是這麼簡單

Java3y發表於2019-03-04

WebService介紹

首先我們來談一下為什麼需要學習webService這樣的一個技術吧….

問題一

如果我們的網站需要提供一個天氣預報這樣一個需求的話,那我們該怎麼做?????

天氣預報這麼一個功能並不是簡單的JS元件就能夠實現的,它的資料是依賴資料庫分析出來的,甚至需要衛星探測..我們個人建站是不可能搞這麼一個資料庫的吧。

那麼既然我們自己幹不了,我們可以去找別人嗎???我們從搜尋引擎搜尋,可以發現很多提供天氣預報的網站,但是它返回的是一個網頁,而我們僅僅需要的是對應的資料

我們可能就在想,我們能不能僅僅只要它返回的資料,而並不是經過加工處理後返回的網頁呢??

於是乎,webService就誕生了,webservice就是一個部署在Web伺服器上的,它向外界暴露出一個能夠通過Web進行呼叫的API。也就是說:當我們想要獲取天氣預報的資訊,我們可以呼叫別人寫好的service服務,我們呼叫就能夠得到結果了

問題二

可是我們寫網站主流的就有好幾個平臺:Java、.net、PHP等等,那麼部署在Web伺服器上的伺服器也就是webserice怎麼能夠就讓我們不同的平臺都能夠呼叫呢??

我們知道java、.net這樣的平臺他們語言的基本資料型別、複雜資料型別就可能不一樣,那麼怎麼能夠實現呼叫的呢???

來引用一段話

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

無論是Java、.net、PHP等等的平臺,只要是網頁開發都是可以通過http協議來進行通訊的,並且返回的資料要是通用的話,那麼我們早就學過這樣的一種技術【XML】

所以webservice實際上就是http+XML

這裡寫圖片描述

對webservice的理解

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

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

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


回顧Socket

我們在學習Java基礎網路程式設計章節已經知道了Scoket這麼一個連線了。

Socket服務端


public class SocketSer {

    public static void main(String[] args) throws Exception {

        ServerSocket ss = new ServerSocket(6666);
        boolean flag = true;
        while (flag) {
            //接收客戶端的請求
            System.out.println("監聽客戶端的資料:");
            Socket sc = ss.accept();
            InputStream is = sc.getInputStream();
            byte[] buffer = new byte[1024];
            int len = -1;
            len = is.read(buffer);
            String getData = new String(buffer, 0, len);
            System.out.println("從客戶端獲取的資料:" + getData);
            //業務處理 大小寫轉化
            String outPutData = getData.toUpperCase();

            //向客戶端寫資料
            OutputStream os = sc.getOutputStream();
            os.write(outPutData.getBytes("UTF-8"));

            //釋放資源
            os.close();
            is.close();
            sc.close();
        }
        ss.close();
    }

}
複製程式碼

Socket客服端


public class SocketClient {

    public static void main(String[] args) throws Exception {
        //獲取使用者輸入的資料
        Scanner input = new Scanner(System.in);
        System.out.println("請輸入資料:");
        String inputData = input.nextLine();

        //開啟一個Socket埠
        Socket sc = new Socket("127.0.0.1", 6666);
        OutputStream os = sc.getOutputStream();
        os.write(inputData.getBytes());

        //獲取服務端回傳的資料
        InputStream is = sc.getInputStream();
        byte[] buffer = new byte[1024];
        int len = -1;
        len = is.read(buffer);
        String getData = new String(buffer, 0, len);
        System.out.println("從服務端獲取的資料:" + getData);
        //是否流
        is.close();
        os.close();
        sc.close();
    }

}
複製程式碼

當我們從客戶端輸入資料以後,那麼服務端就會把資料轉成是大寫

這裡寫圖片描述
這裡寫圖片描述

其實HTTP協議就是基於Socket對其進行封裝,我們也可以在IE瀏覽器中對其進行訪問.我們一樣能夠獲取得到資料!

這裡寫圖片描述
這裡寫圖片描述

Scoket與HTTP簡述

這裡寫圖片描述

ISO的七層模型 : 物理層、資料鏈路層、網路層、傳輸層、表示層、會話層、應用層

  • Socket訪問 : Socket屬於傳輸層,它是對Tcp/ip協議的實現,包含TCP/UDP,它是所有通訊協議的基礎,Http協議需要Socket支援,以Socket作為基礎

  • Socket通訊特點:

    • 開啟埠,該通訊是 長連線的通訊 ,很容易被防火牆攔截,可以通過心跳機制來實現 ,開發難度大
    • 傳輸的資料一般是字串 ,可讀性不強
    • socket埠不便於推廣
    • 效能相對於其他的通訊協議是最優的
  • Http協議訪問 :屬於應用層的協議,對Socket進行了封裝

    • 跨平臺
    • 傳資料不夠友好
    • 對第三方應用提供的服務,希望對外暴露服務介面
      問題:
  •     **資料封裝不夠友好 :可以用xml封裝資料 **
    複製程式碼
  •     **希望給第三方應用提供web方式的服務  (http + xml) = web  Service**
    複製程式碼

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

快速入門

首先,我們來嘗試一下呼叫別人寫好的webService,來體驗一把:我們訪問www.webxml.com.cn/zh_cn/index…

這裡寫圖片描述

進入到裡邊

這裡寫圖片描述

當我們輸入一個號碼,它就能夠查詢出我們的手機位置資訊:

WebService就是這麼簡單

我們現在要做的就是將這個服務讓我們自己寫的應用程式中也可以呼叫,那怎麼做呢???

http-get方式訪問webservice

這裡寫圖片描述

public void get(String mobileCode ,String userID ) throws Exception{
		URL url=new URL("http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx/getMobileCodeInfo?mobileCode="+mobileCode+
				"&userID="+userID);
		HttpURLConnection conn=(HttpURLConnection) url.openConnection();
		conn.setConnectTimeout(5000);
		conn.setRequestMethod("GET");
		if(conn.getResponseCode()==HttpURLConnection.HTTP_OK){ //結果碼=200
			InputStream is=conn.getInputStream();
			//記憶體流 ,  
			ByteArrayOutputStream boas=new ByteArrayOutputStream();
			byte[] buffer=new byte[1024];
			int len=-1;
			while((len=is.read(buffer))!=-1){
				boas.write(buffer, 0, len);
			}
			System.out.println("GET請求獲取的資料:"+boas.toString());
			boas.close();
			is.close();
		}
	}
複製程式碼
這裡寫圖片描述

Http-Client 框架POST請求

為什麼要使用HttpClient工具:

  • 原生態的Socket基於傳輸層,現在我們要訪問的WebService是基於HTTP的屬於應用層,所以我們的Socket通訊要藉助HttpClient發HTTP請求,這樣格式才能匹配

HttpClient使用步驟如下:

  1. 建立 HttpClient 的例項
  2. 建立某種連線方法的例項,在這裡是 GetMethod。在 GetMethod 的建構函式中傳入待連線的地址
  3. 配置要傳輸的引數,和訊息頭資訊
  4. 呼叫第一步中建立好的例項的 execute 方法來執行第二步中建立好的 method 例項
  5. 通過response讀取字串
  6. 釋放連線。無論執行方法是否成功,都必須釋放連線

	//2.Post請求 :通過Http-Client 框架來模擬實現 Http請求
	public void post(String mobileCode ,String userID) throws Exception{

/**HttpClient訪問網路的實現步驟:
		 *  1. 準備一個請求客戶端:瀏覽器 
		 *  2. 準備請求方式: GET 、POST
		 *  3. 設定要傳遞的引數
		 *  4.執行請求
		 *  5. 獲取結果
		 */
		HttpClient client=new HttpClient();
		PostMethod postMethod=new PostMethod("http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx/getMobileCodeInfo");
		//3.設定請求引數
		postMethod.setParameter("mobileCode", mobileCode);
		postMethod.setParameter("userID", userID);
		//4.執行請求 ,結果碼
		int code=client.executeMethod(postMethod);
		//5. 獲取結果
		String result=postMethod.getResponseBodyAsString();
		System.out.println("Post請求的結果:"+result);
	}


	//2.Post請求 :通過Http-Client 框架來模擬實現 Http請求
	public void soap() throws Exception{

		HttpClient client=new HttpClient();
		PostMethod postMethod=new PostMethod("http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx");
		//3.設定請求引數
          postMethod.setRequestBody(new FileInputStream("c:/soap.xml"));
          //修改請求的頭部
          postMethod.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
		//4.執行請求 ,結果碼
		int code=client.executeMethod(postMethod);
		System.out.println("結果碼:"+code);
		//5. 獲取結果
		String result=postMethod.getResponseBodyAsString();
		System.out.println("Post請求的結果:"+result);
	}

複製程式碼

wsimport

上面我們使用的是GET方式或者使用Http-Client框架來呼叫webservice的服務,其實這兩種方式也有弊端

  • 傳遞引數麻煩【get方式都寫在請求地址上、post方式要一個一個封裝】
  • 解析結果麻煩【根據返回的XML來解析字串】

如果我們可以把整個物件傳遞進去,返回的結果更加友好的話,就好像我們平常呼叫Java類一樣使用webservice就好咯

Java也提供了類似的方法,把webservice服務搞成是Java類讓我們自己呼叫,既然是Java類的話,那麼我們使用起來就非常方便了!

把webservice服務搞成是Java類讓我們自己呼叫其實就是Java幫我們生成本地代理,再通過本地代理來訪問webservice

快速入門

wsimport是Java自帶的一個命令,我們想要使用該命令,就必須配置環境變數,並且jdk的版本最好是1.7或以上

值得注意的是:ide帶的JDK版本要和wsimport生成本地的版本一致,不然就用不了!!!

  • wsimport使用:
    wsimport命令後面跟著的是WSDL的url路徑 語法 wsimport [opations] <wsdl_uri>
    •    wsdl_uri:wsdl 的統一資源識別符號
      複製程式碼
    •    d  :指定要輸出的檔案的位置
      複製程式碼
    •    s  :表示要解析java的原始碼 ,預設解析出的是class位元組碼 
      複製程式碼
    •    p  : 指定輸出的包名
      複製程式碼
這裡寫圖片描述

首先我們先把cmd的路徑退到桌面上:

這裡寫圖片描述

然後對WSDL檔案生成本地代理

這裡寫圖片描述
這裡寫圖片描述

該本地代理其實就是一堆的位元組碼檔案

這裡寫圖片描述

將得到的位元組碼檔案打包成jar,那麼我們只要在專案中匯入jar包,就可以呼叫了!

語法


jar cvf  test.jar【jar包的名稱】 打包目錄

複製程式碼
這裡寫圖片描述

本來我是想將本地代理的class檔案生成jar包,然後匯入到idea環境下,那麼直接呼叫就行了。可是idea老是報出找不到對應的類,找了半天也找不到,很煩呀!!!!我考慮了以下的幾種情況

  • ** 生成的class檔案的JVM和idea下的JVM環境不匹配【後來切換了也不行】**
  • idea快取原因,把idea所有快取去掉也不行
  • 生成的本地代理包名cn不行【???idea就是對cn這個包名報錯,後來我改成自定義的包名也不行】

最後我還是沒有找到辦法,如果知道是什麼原因的,麻煩在評論中告訴我吧….因此這次的測試import,我就不僅僅生成class位元組碼檔案,還生成了.java檔案。我就直接使用java檔案來測試了。

在zhongfucheng目錄下生成本地代理,把java原始碼也帶上

這裡寫圖片描述

於是我就把java原始碼複製到我的專案中,用java原始碼來進行測試

這裡寫圖片描述

解析WSDL

有的同學可能會疑問,為啥wsimport能那麼厲害,將http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?WSDL這麼一個url生成本地代理,其實我們看了WSDL檔案就知道了。

這裡寫圖片描述

值得注意的是,本地代理僅僅是有其方法,類,並不能解析出具體的實現的。具體的操作其實還是webservice去完成的。代理這麼一個概念就更加清晰了。

自定義webservice服務

我們在上一章節中已經使用wsimport生成本地代理來呼叫webservice的服務了,其實我們自己寫的web應用程式也是可以釋出webservice的

我們釋出了webservice的話,那麼其他人也是可以呼叫我們自己寫的webservice!

那麼我們怎麼自定義webservice然後釋出出去呢???

在jdk 1.6 版本以後 ,**通過jax-ws 包提供對webservice的支援 **

  • 該方式通過註解的方式來宣告webservice
  • 通過 jdk EndPoint.publish()釋出webserive服務

快速入門

寫一個實體:


public class Phone {
	private String name;//作業系統名
	private String owner;//擁有者 
	private int total;//市場佔有率
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getOwner() {
		return owner;
	}
	public void setOwner(String owner) {
		this.owner = owner;
	}
	public int getTotal() {
		return total;
	}
	public void setTotal(int total) {
		this.total = total;
	}

}

複製程式碼

釋出service,通過註解來讓WSDL檔案更加可讀…


package cn.it.ws.d;

import cn.it.ws.model.Phone;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.ws.Endpoint;
/*
*手機的業務類,該業務類通過webservice 對外提供服務
 * 1. 宣告: @webservice
 * 2. 釋出 EndPoint
 */

@WebService (serviceName="PhoneManager",//修改服務名
   targetNamespace="http://dd.ws.it.cn") //修改名稱空間 ,預設包名,取反
//宣告該業務類 對外提供webservice服務   ,預設只是對public 修飾的方法對外以webservice形式釋出
public class PhoneService {

/**@WebMethod(operationName="getMObileInfo"): 修改方法名
	 * @WebResult(name="phone"):修改返回引數名
	 * @WebParam(name="osName"):修改輸入引數名
	 */

	@WebMethod(operationName="getMObileInfo")
	public @WebResult(name="phone") Phone getPhoneInfo(@WebParam(name="osName")String osName){
		Phone phone=new Phone();
		if(osName.endsWith("android")){
			phone.setName("android");phone.setOwner("google");phone.setTotal(80);
		}else if(osName.endsWith("ios")){
			phone.setName("ios");phone.setOwner("apple");phone.setTotal(15);
		}else{
			phone.setName("windows phone");phone.setOwner("microsoft");phone.setTotal(5);
		}
		return phone;
	}
	@WebMethod(exclude=true)//把該方法排除在外
	public void sayHello(String city){
		System.out.println("你好:"+city);
	}
	private void sayLuck(String city){
		System.out.println("好友:"+city);
	}
	 void sayGoodBye(String city){
		System.out.println("拜拜:"+city);
	}
	protected void saySayalala(String city){
		 System.out.println("再見!"+city);
	 }
	
	public static void main(String[] args) {
		String address1="http://127.0.0.1:8888/ws/phoneService";
//		String address2="http://127.0.0.1:8888/ws/phoneManager";
/**
		 * 釋出webservice服務
		 * 1.address:服務的地址
		 * 2:implementor 服務的實現物件
		 */

		Endpoint.publish(address1, new PhoneService());
//		Endpoint.publish(address2, new PhoneService());
		System.out.println("wsdl地址 :"+address1+"?WSDL");
	}

}

複製程式碼
  1. 在類上新增@WebService註解,代表釋出一個WebService服務
  2. 通過EndPoint(端點服務)釋出一個webService。Endpoint也是jdk提供的一個專門用於釋出服務的類,它的publish方法接收兩個引數,一個是本地的服務地址,二是提供服務的類。它位於javax.xml.ws.*包中。
  3. Endpoint.publish(String address, Object implementor) 靜態方法在給定地址處針對指定的實現者物件建立併發布端點
  4. 給類新增上@WebService註解後,類中所有的非靜態方法都將會對外公佈
  5. 如果希望某個方法不對外公開,可以在方法上新增@WebMethod(exclude=true),阻止對外公開。
  6. 如果一個類上,被新增了@WebService註解,則必須此類至少有一個可以公開的方法,否則將會啟動失敗。
    protected、private、final、static方法不能對外公開

@WebService	// 新增了此註解,代表是一個WebService
public class HelloWorld {
	// 非 static final private 方法預設會發布
	public String sayHi(String name) {
		return "hello" + name;
	}
	@WebMethod(exclude=true)
	public void exclude(){
		// 被註解排除的方法
	}
	protected void protected1(){
		//受保護的方法預設不釋出
	}
	private void private1(){
		// 私有方法預設不釋出
	}
	public static void static1(){
		// static 方法預設不釋出
	}
	public final void final1(){
		// final 方法預設不釋出
	}
}
複製程式碼
這裡寫圖片描述

生成的webservice能夠在瀏覽器訪問

這裡寫圖片描述

SOAP協議

這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述

目前WebService的協議主要有SOAP1.1和1.2。

  • 兩者的名稱空間不同。
    • Soap1.1的名稱空間:
      • xmlns:soap=“http://schemas.xmlsoap.org/soap/envelope/ “
    • Soap1.2 名稱空間:
      • xmlns:soap="http://www.w3.org/2003/05/soap-envelope“ 
        複製程式碼
  • SOAP1.1版本與SOAP1.2版本在頭資訊上存在差異。
    • SOAP1.1存在SOAPAction的請求頭。
    • SOAP1.2沒有SOAPAction的請求頭。
  • 基於SOAP1.1生成的WSDL和基於SOAP1.2生成的WSDL也不一樣。
    主要看名稱空間。
  • 在CXF中兩種協議請求的方式也不一樣。
    • 1.1為content-Type:text/xm;charset=UTF-8
    • 1.2為content-Type:application/soap+xml;charset=UTF-8
這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述

SOA、UDDI概念

SOA

Soa(Service-Oriented Architecture)面向服務的架構,它是一種思想,IBM大力倡導是即插即用的,IBM大力提倡,希望以組裝電腦的方式來開發應用

組成:

  •       面向web的服務,面向web的元件  :WebService : 硬碟、cpu、記憶體條
    複製程式碼
  •       企業服務匯流排 (EnterPrise Service Bus :ESB)。主機板
    複製程式碼

uddi

uddi (Universal Description, Discovery and Integration)統一描述、發現、整合

  • 它是目錄服務,通過該服務可以註冊和釋出webservcie,以便第三方的呼叫者統一呼叫
  • 用得並不太多。

實現介面的webservice

服務端


import javax.jws.WebService;

/**面向介面的webservice釋出方式
 * 
 * 
 */
@WebService
public interface JobService {
	public String getJob();
}



複製程式碼



import javax.jws.WebService;

@WebService(endpointInterface="cn.it.ws.e.JobService")//設定服務端點介面 ,指定對外提供服務的介面
public class JobServiceImpl implements JobService {

	@Override
	public String getJob() {
		return "JEE研發工程師|Android研發工程師|資料庫工程師|前端工程師|測試工程師|運維工程師";
	}
    public void say(){
    	System.out.println("早上好!");
    }
}

複製程式碼

客戶端


import javax.xml.ws.Endpoint;

public class Test {

	public static void main(String[] args) {
		JobService jobService=new JobServiceImpl();
		String address="http://192.168.114.10:9999/ws/jobservice";
		Endpoint.publish(address, jobService);
		System.out.println("wsdl地址:"+address+"?WSDL");

	}

}
複製程式碼

CXF框架

Apache CXF 是一個開源的 Services 框架,CXF 幫助您來構建和開發 Services 這些 Services 可以支援多種協議,比如:SOAP、POST/HTTP、RESTful HTTP CXF 大大簡化了 Service可以天然地和 Spring 進行無縫整合。

CXF介紹 :soa的框架

  • * cxf 是 Celtrix (ESB框架)和 XFire(webserivice) 合併而成,並且捐給了apache  
    複製程式碼
  • * CxF的核心是org.apache.cxf.Bus(匯流排),類似於Spring的 ApplicationContext
    複製程式碼
  • * CXF預設是依賴於Spring的
    複製程式碼
  • * Apache CXF 發行包中的jar,如果全部放到lib中,需要 JDK1.6 及以上,否則會報JAX-WS版本不一致的問題
    複製程式碼
  • * CXF 內建了Jetty伺服器 ,它是servlet容器,好比tomcat
    複製程式碼

CXF特點

  • 與Spring、Servlet做了無縫對接,cxf框架裡面整合了Servlet容器Jetty
  • 支援註解的方式來發布webservice
  • 能夠顯示一個webservice的服務列表
  • 能夠新增攔截器:輸入攔截器、輸出攔截器 :
  • 輸入日誌資訊攔截器、輸出日誌攔截器、使用者許可權認證的攔截器

CXF開發

要想使用CXF框架,那麼就先匯入jar包

  • asm-3.3.jar
  • commons-logging-1.1.1.jar
  • cxf-2.4.2.jar
  • jetty-continuation-7.4.5.v20110725.jar
  • jetty-http-7.4.5.v20110725.jar
  • jetty-io-7.4.5.v20110725.jar
  • jetty-security-7.4.5.v20110725.jar
  • jetty-server-7.4.5.v20110725.jar
  • jetty-util-7.4.5.v20110725.jar
  • neethi-3.0.1.jar
  • wsdl4j-1.6.2.jar
  • xmlschema-core-2.0.jar

介面


		import javax.jws.WebParam;
		import javax.jws.WebResult;
		import javax.jws.WebService;

@WebService(serviceName="languageManager")
public interface LanguageService {
	public @WebResult(name="language")String getLanguage(@WebParam(name="position")int position);

}
複製程式碼

實現:


package cn.it.ws.cxf.a;

import org.apache.cxf.frontend.ServerFactoryBean;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;

/**開發語言排行描述服務
 * 
 * 
 * @author 李俊  2015年5月17日
 */
public class LanguageServiceImpl implements LanguageService {
	/* (non-Javadoc)
	 * @see cn.it.ws.cxf.a.LanguageService#getLanguage(int)
	 */
	@Override
	public String getLanguage(int position){
		String language=null;
		switch (position) {
		case 1:
			language="java"; 
			break;
		case 2:
			language="C";
			break;
		case 3:
			language="Objective-C";
			break;  
		case 4:
			language="C#";
			break;

		default:
			break;
		}
		return language;
	}
	/**通過cxf框架釋出webservice
	 *  1. ServerFactoryBean
	 *    - 不設定註解也可以釋出webservice服務, 不支援註解
	 *    - 不支援攔截器的新增
	 *  2. JaxWsServerFactoryBean
	 *    - 支援註解
	 *    - 可以新增攔截器
	 *  3. webservice 訪問流程:
	 *    1. 檢測本地代理描述的wsdl是否與服務端的wsdl一致 ,俗稱為握手
	 *    2. 通過soap協議實現通訊 ,採用的是post請求 , 資料封裝在滿足soap規約的xml中
	 *    3. 返回資料 同樣採用的是soap通訊,  資料封裝在滿足soap規約的xml中
	 * @param args
	
	public static void main(String[] args) {
		LanguageService languageService=new LanguageServiceImpl();
		ServerFactoryBean bean=new ServerFactoryBean();
		//Endpoint :地址  , 實現物件
		bean.setAddress("http://192.168.114.10:9999/ws/cxf/languangeService");
		bean.setServiceClass(LanguageService.class);//對外提供webservcie的業務類或者介面
		bean.setServiceBean(languageService);//服務的實現bean
		bean.create();//建立,釋出webservice
		System.out.println("wsdl地址:http://192.168.114.10:9999/ws/cxf/languangeService?WSDL");
	}
	 */
	public static void main(String[] args) {
		LanguageService languageService=new LanguageServiceImpl();
		JaxWsServerFactoryBean bean=new JaxWsServerFactoryBean();
		//Endpoint :地址  , 實現物件
		bean.setAddress("http://192.168.114.10:9999/ws/cxf/languangeService");
		bean.setServiceClass(LanguageService.class);//對外提供webservcie的業務類或者介面
		bean.setServiceBean(languageService);//服務的實現bean
		//新增輸入攔截器  :輸入顯示日誌資訊的攔截器
		bean.getInInterceptors().add(new LoggingInInterceptor());
		//新增輸出攔截器  :輸出顯示日誌資訊的攔截器
		bean.getOutInterceptors().add(new LoggingOutInterceptor());
		
		bean.create();//建立,釋出webservice
		System.out.println("wsdl地址:http://192.168.114.10:9999/ws/cxf/languangeService?WSDL");
	}

}

複製程式碼

CXF與Spring整合

  • 建立一個web專案
  • 準備所有jar包,將CXF_HOMElib專案下的所有jar包,全部都拷貝新專案的lib目錄下.其中裡面已經包含了Sring3.0的jar包 其中jetty 伺服器的包可以不要.因為我們要部署的tomcat伺服器中了
  • 在web.xml中配置cxf的核心servlet,CXFServlet
  • 此配置檔案的作用類 攔截/ws/*的所有請求 類似Struts2的過濾器

web.xml配置檔案:


<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">
    <display-name>CXF_Server</display-name>
    <!-- 新增  CXF 的Servlet ,處理 webservice的請求 -->
    <servlet>
        <servlet-name>cxf</servlet-name>
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
        <load-on-startup>0</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>cxf</servlet-name>
        <url-pattern>/ws/*</url-pattern>
    </servlet-mapping>
    <!-- Spring 監聽新增 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
</web-app>
複製程式碼

實體:


public class Employee {
	private Integer  id;
	private String name;
	private Integer age;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}

}

複製程式碼

介面:



package cn.it.ws.cxf.b;

import java.util.List;

import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;

import cn.it.ws.cxf.bean.Employee;
@WebService(serviceName="EmployeeService")
public interface EmployeeManager {

	void add(@WebParam(name="employee")Employee employee);

	@WebResult(name="employees")List<Employee> query();

}
複製程式碼

介面實現:


package cn.it.ws.cxf.b;

import java.util.ArrayList;
import java.util.List;

import cn.it.ws.cxf.bean.Employee;

/**員工管理的業務實現類
 * @author 李俊  2015年5月17日
 */
public class EmployeeManagerImpl implements EmployeeManager {
	private List<Employee> employees=new ArrayList<>();
	@Override
	public void add(Employee employee){
		//新增到集合中
		employees.add(employee);
	}
	@Override
	public List<Employee> query(){
		return employees;
	}

}

複製程式碼

Spring配置資訊:


<?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:p="http://www.springframework.org/schema/p"
        xmlns:jaxws="http://cxf.apache.org/jaxws"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
	  http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">


    <bean id="employeeManagerImpl" class="cn.it.ws.cxf.b.EmployeeManagerImpl"></bean>
    <!-- 配置cxf
       地址:      http://192.168.114.10:8080/CXF_Server/ws/employeeManager
       組成 :  http://192.168.114.10:8080 +CXF_Server( 專案名)+ws(過濾的路徑)+/employeeManager(自定義部分)
       服務類 :
       服務的實現類:
       攔截器
        -->
    <jaxws:server address="/employeeManager" serviceClass="cn.it.ws.cxf.b.EmployeeManager">
        <jaxws:serviceBean>
            <ref bean="employeeManagerImpl"/>
        </jaxws:serviceBean>
        <!-- 配置輸入顯示日誌資訊的攔截器   -->
        <jaxws:inInterceptors>
            <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
        </jaxws:inInterceptors>
        <jaxws:outInterceptors>
            <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>
        </jaxws:outInterceptors>
    </jaxws:server>


</beans>
複製程式碼

IDEA下使用webservice

我們的Intellij idea是一個非常好用的java ide,當然了,它也支援webservice開發。非常好用…由於在網上見到的教程非常多,我就貼幾個我認為比較好的教程:

www.biliyu.com/article/986…

blog.csdn.net/u010323023/…

blog.csdn.net/dreamfly88/…

獲取天氣預報

我們現在webservice就基本入門了,現在我想要做的就是自己寫的網站能夠拿到天氣預報的資訊,於是我去www.webxml.com.cn/zh_cn/index…找到了天氣預報的服務

這個是天氣預報的WSDL地址:ws.webxml.com.cn/WebServices…,那麼我們只要解析該WSDL服務即可

這裡寫圖片描述

如果不想得到所有的資訊,那麼我們可以在服務上找到我們想要對應的資料,也就是說:

這裡寫圖片描述
這裡寫圖片描述

總結

  • 應用webservice的原因就在於我們需要一些服務、這些服務是我們自己不能手動寫的。比如天氣預報,於是就出現了webService技術。webService能夠讓我們可以獲取網上別人釋出出來的服務。我們只要呼叫它,就可以獲取相關的資料了。
  • Socket其實就是對TCP/IP協議的一個封裝,而我們在網上使用的是HTTP協議。WebService也是Web應用程式。它也當然支援HTTP協議了。不過WebService需要給不同語言都能夠使用,因此它使用XML來進行傳輸。
  • 於是,它就有自己一種協議**:SOAP(簡單物件訪問協議)。其實SOAP就是Http+XML**。
  • 我們可以使用http-get方式訪問webservice,由於它使用的是原生Socket來進行訪問。會有點複雜。於是我們可以藉助Http-Client 框架來訪問WebService。Http-Client 框架比HTTP-GET方式會簡單一點。但還是不夠簡潔。
  • 最後,我們可以使用Java自帶的WsImport來實現本地代理。這種方法會將WebService翻譯成Java類,我們使用類一樣去訪問WebService就行了。非常好用。
  • 我們是可以自己寫webService的。對服務類上加上註解。通過EndPoint(端點服務)就能夠把我們webService服務類釋出出去了。
    • 為了讓WDSL檔案更加讀取,可以使用註解的方式來寫好對應的引數名稱。
    • 也可以控制某方法是否被髮布出去
  • SOAP其實上就是使用XML進行傳輸的HTTP協議。
  • SOA:面向服務架構。即插即用。也就是耦合非常低,用的時候加上就行了。
  • UDDI (Universal Description, Discovery and Integration)統一描述、發現、整合,其實就是一個webservice的目錄結構,不過我們很少把webservice釋出到上面去
  • 實現介面的webservice只是在類上對其的一種抽象而已,沒什麼大不了的。
  • CXF框架可以與spring無縫連線,就不用我們自己Endpoint了。它還能記錄日誌之類的。
  • 我們還可以使用Idea下的webservice,能夠使用圖形畫面的方式獲取本地代理和生成WSDL檔案。

如果文章有錯的地方歡迎指正,大家互相交流。習慣在微信看技術文章,想要獲取更多的Java資源的同學,可以關注微信公眾號:Java3y

相關文章