1. 程式人生 > >Java進階學習第三十四天(WebService)

Java進階學習第三十四天(WebService)

一、WebService介紹

1、使用場景
① 不同的移動客戶端訪問
② 需要訪問第三方的專案

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

3、基於Socket建立Web服務
Socket原理圖
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();
	}
}

4、訪問第三方應用的方式
① Socket訪問:Socket屬於傳輸層,它是對Tcp/ip協議的實現,包含TCP/UDP,它是所有通訊協議的基礎,Http協議需要Socket支援,以Socket作為基礎
特點:
◇ 開啟埠,該通訊是長連線的通訊 ,很容易被防火牆攔截,可以通過心跳機制來實現 ,開發難度大
◇ 傳輸的資料一般是字串 ,可讀性不強
◇ socket埠不便於推廣:http:17.23.23.2:2345不如像www.jd.com
◇ 但是效能相對於其他的通訊協議是最優的
② Http協議訪問:屬於應用層的協議,對Socket進行了封裝
特點:
◇ 跨平臺
◇ 傳資料不夠友好 : http://127.0.0.1:8888?username=lj&pwd=1234


◇ 對第三方應用提供的服務,一般就是封裝好的一個網頁
③ Webservice:(http + xml) = web Service

5、WebService概念
Web Service是 能使得執行在不同機器上的不同應用無須藉助附加的、專門的第三方軟體或硬體, 就可相互交換資料或整合。依據Web Service規範實施的應用之間, 無論它們所使用的語言、平臺或內部協議是什麼, 都可以相互交換資料,通俗的講,Web Service就是一個部署在Web伺服器上的一個,它向外界暴露出一個能夠通過Web進行呼叫的API。這就是說,你能夠用程式設計的方法通過Web來呼叫這個應用程式。我們把呼叫這個Web Service 的應用程式叫做客戶端,釋出這個web服務的機應用程式器稱為Web Service伺服器。

6、WebService技術規則
① 基於web的系統級介面規範
◇ 一個普通適用標準 :http+xml
◇ 任何網路通訊的作業系統
◇ 自包含、自描述、模組化
◇ 釋出、定位、通過web呼叫
② web service 技術和規則
◇ xml(可拓展標記語言)
◇ soap(簡易物件訪問協議)
◇ wsdl(web services 描述語言)
◇ uddi(通用描述、發現及整合)
③ 跨平臺的可互操作性
◇ 基於xml
◇ 基於xsd(xml schema )
◇ 基於http
④ webservice 適用場景
◇ 跨防火牆的通訊
◇ 異構系統間應用程式整合(jee:(EJB RMI)、php、c++、.net (com+))

7、WebService的優勢
① 異構平臺的互通性
理論上, Web Service 最大的優勢是提供了異構平臺的無縫街接技術手段。由於不同的使用者使用不同的硬體平臺,不同的操作平臺,不同的作業系統,不同的軟體,不同的協議通訊,這就產生了互相通訊的需求。 Web Service 使任何兩個應用程式,只要能讀寫XML,那麼就能互相通訊
② 更廣泛的軟體複用
軟體的複用技術通過組合已有模組來搭建應用程式,能大幅度提高軟體的生產效率和質量。使用者只要獲得了描述 Web Service 的 WSDL 檔案,就可以方便地生成客戶端代理,並通過代理訪問 Web Service
③ 成本低、可讀性強、應用範圍廣
Web Service 可用基於 XML 的 SOAP 來表示資料和呼叫請求。並且通過 HTTP 協議傳輸 XML 格式的資料
④ 迅捷的軟體發行方式
Web Service 將徹底地改變軟體的發行方式。軟體供應商可以把軟體分解成若Web Service 模組構成的系統,直接在 Web 上釋出

8、WebService專業名稱
① XML:Extensible Markup Language ,擴充套件性標記語言,用於傳輸格式化的資料,是Web服務的基礎。
◇ namespace-名稱空間。
xmlns=“http://itcast.cn” 使用預設名稱空間。
xmlns:itcast=“http://itcast.cn”使用指定名稱的名稱空間。
② WSDL: WebService Description Language – Web服務描述語言,呼叫該webservice api 的介面描述
◇ 通過XML形式說明服務在什麼地方:地址。
◇ 通過XML形式說明服務提供什麼樣的方法 :如何呼叫
③ SOAP: Simple Object Access Protocol(簡單物件訪問協議)
SOAP作為一個基於XML語言的協議用於有網上傳輸資料,SOAP = 在HTTP的基礎上+XML資料。SOAP是基於HTTP的。
SOAP的組成如下:
◇ Envelope – 必須的部分,以XML的根元素出現。
◇ Headers – 可選的。
◇ Body – 必須的,在body部分,包含要執行的伺服器的方法和傳送到伺服器的資料。

二、呼叫第三方的WebService服務

1、體驗webservice:登入http://www.webxml.com.cn

2、HttpClient工具
HttpClient 是 Apache Jakarta Common 下的子專案,可以用來提供高效的、最新的、功能豐富的支援 HTTP 協議的客戶端程式設計工具包,並且它支援 HTTP 協議最新的版本和建議。
HttpClient使用步驟如下:
① 建立 HttpClient 的例項
② 建立某種連線方法的例項,在這裡是 GetMethod。在 GetMethod 的建構函式中傳入待連線的地址
③ 配置要傳輸的引數和訊息頭資訊
④ 呼叫第一步中建立好的例項的 execute 方法來執行第二步中建立好的 method 例項
⑤ 通過response讀取字串
⑥ 釋放連線,無論執行方法是否成功,都必須釋放連線

3、準備客戶端,呼叫第三方的webservice服務,讓本專案有手機查號的功能
一般訪問方式通過HttpClient
① Http-GET
② Http-Post
③ Soap (http+xml)

public class MobileCodeService {
	//1. get方式訪問webservice
	public void get(String mobileCode ,String userID ) throws Exception{
		URL url=new URL("http://webservice.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();
		}
	}
	
	//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://webservice.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);
	}
	
	//3.soap
	public void soap() throws Exception{
		HttpClient client=new HttpClient();
		PostMethod postMethod=new PostMethod("http://webservice.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);
	}

        //Java方式訪問WebService
	public static void main(String[] args) throws Exception{
		MobileCodeService ws=new MobileCodeService();
		ws.get("15626217879", "");
		ws.post("15626217879", "");
//		ws.soap();
	}
}

webservice 納入w3c規範,其他的平臺都支援該規範,都支援wsimport 方式 (對遠端的webservice生成本地代理,再通過本地代理來訪問webservice)
① wsimport 命令的位置: C:\Program Files\Java\jdk1.7.0_04\bin
② 要求:
jdk的版本要在 jdk 1.6.21及以上,作業系統安裝的jdk版本與MyEclispe及預設指定的版本要一致
③ wsimport使用: 記得設定jdk\bin 環境變數 指定path
④ 語法:wsimport [opations] <wsdl_uri>

- wsdl_uri:wsdl 的統一資源識別符號
- d  :指定要輸出的檔案的位置
- s  :表示要解析java的原始碼 ,預設解析出的是class位元組碼 
- p  : 指定輸出的包名

通過wsimport生成本地代理來訪問 webservice服務端

	public static void main(String[] args) {
		//生成服務物件
		MobileCodeWS ws=new MobileCodeWS();
		//取得webservice服務的訪問方式: Soap1.1、Soap 1.2、Http-get、http-Post
		MobileCodeWSSoap mobileCodeWSSoap = ws.getMobileCodeWSSoap();
		/**
		 *  返回的資料有兩種型別 : 
		 *  1. 簡單的資料型別,基本資料型別:整數、布林、字串等
		 *  2. 複合的資料型別:結構體、陣列、物件 
		 */
		//1.簡單的資料
		String result=mobileCodeWSSoap.getMobileCodeInfo("13660559129", "");
		System.out.println("返回的結果:"+result);
		//2. 複合的資料  List<String> List<Student>
		ArrayOfString databaseInfo = mobileCodeWSSoap.getDatabaseInfo();
		List<String> results=databaseInfo.getString();
		//遍歷集合
		for(String temp:results){
			System.out.println(temp);
		}
		//jsp  Select 
	}
}

4、自定義及釋出一個webservice服務
① 宣告某個業務服務為webservice服務:通過@webservice註解來宣告
② 釋出webservice服務:Endpoint.publish()釋出

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;
	}
}
/**手機的業務類,該業務類通過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://192.168.114.10: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");
	}
}

③ 通過wsimport生成本地代理來訪問自己釋出的webservice:wsimport

public class _Main {
	public static void main(String[] args) {
		//服務
		PhoneServiceService ws=new PhoneServiceService();
		//訪問方式 
		PhoneService phoneServicePort = ws.getPhoneServicePort();
		Phone phoneInfo = phoneServicePort.getPhoneInfo("android");
		System.out.println(phoneInfo.getName());
		System.out.println(phoneInfo.getOwner());
		System.out.println(phoneInfo.getTotal());
	}
}

5、需求:
① 想改方法的輸入引數名、返回引數名
② 想改服務名,方法名
③ 對該業務類的某些方法不想對外發布
預設只有public 修飾的方法會以webservice的形式對外發布,而 private 受保護的、預設的,都不會發布;我想讓某些public 方法也不對外發布
解決方法:通過註解配置修改wsdl檔案, 讓它具有更好的可讀性

6、呼叫教師機的ws服務步驟:
① 系統jdk環境與myeclipse jdk 環境一致:1.6.021以上
② 服務端的WDSL路徑http://192.168.114.10:8888/ws/phoneService?WSDL
③ 命令列 wsimport -s ./ -p cn.itcast.ws.d http://192.168.114.10:8888/ws/phoneService?WSDL
④ 匯入通過wsimport 解析的java類,再編寫一個main測試

7、WSDL檔案介紹 :webservice服務說明
① WSDL 文件的組成部分

元素 定義
<portType> web service 執行的操作
<message> web service 使用的訊息
<types> web service 使用的資料型別
<binding> web service 使用的通訊協議

② WSDL 文件的主要結構

<definitions>
<types>
	definition of types........
</types>
<message>
	definition of a message....
</message>
<portType>
	definition of a port.......
</portType>
<binding>
	definition of a binding....
</binding>
</definitions>

③ WSDL元素介紹
定義一個功能,在Java中叫做方法,在C中叫做函式;在Java中叫類,在C語言中叫做結構體。這些名詞都不一樣。WSDL規範為了不會產生歧義,就定義了一些新的名詞來表述功能與服務。
<portType>(WSDL埠)
<portType> 元素是最重要的 WSDL 元素。 它可描述一個 web service、可被執行的操作,以及相關的訊息。 可以把 元素比作傳統程式語言中的一個函式庫(或一個模組、或一個類)。
<operation>子元素:
對服務中所支援的操作的抽象描述,一般單個Operation描述了一個訪問入口的請求/響應訊息對。
<message> (WSDL訊息)
<message> 元素定義一個操作的資料元素。 每個訊息均由一個或多個部件組成。可以把這些部件比作傳統程式語言中一個函式呼叫的引數。
通訊訊息的資料結構的抽象型別化定義。使用Types所定義的型別來定義整個訊息的資料結構。
<types>(WSDL types)
<types> 元素定義 web service 使用的資料型別。 為了最大程度的平臺中立性,WSDL 使用 XML Schema 語法來定義資料型別。
<binding> (WSDL Bindings)
<binding> 元素為每個埠定義訊息格式和協議細節。

<message name="getTermRequest">
   <part name="term" type="xs:string"/>
</message>

<message name="getTermResponse">
   <part name="value" type="xs:string"/>
</message>

<portType name="glossaryTerms">
  <operation name="getTerm">
        <input message="getTermRequest"/>
        <output message="getTermResponse"/>
  </operation>
</portType>

8、四個概念
① soap:簡單物件訪問協議,包含http+xml
② Soa:面向服務的架構,它是一種思想,IBM大力提倡服務都是面向web的 ,而且是即插即用的,它有兩部分組成:
◇ 面向web的服務或者是面向web的元件:WebServic(就像硬碟、cpu、記憶體條)
◇ 企業服務匯流排:EnterPrise Service Bus ,ESB(就像主機板)
③ wsdl:webservice 描述語言
④ uddi:Universal Description, Discovery and Integration
統一描述、發現、整合,它是目錄服務,通過該服務可以註冊和釋出webservcie,以便第三方的呼叫者統一呼叫

9、兩個思考
① 思考:webservice在web應用的三層架構中,位於哪一層中呢?
屬於業務層,即Service層
② 思考:你覺得webservice有嚴格的客戶端和服務端嗎?
沒有,相對服務端和客戶端

三、帶有介面的webservice釋出方式

1、通過EndPoint釋出帶有介面的webservice

/*
* 面向介面的webservice釋出方式
 */
@WebService
public interface JobService {
	public String getJob();
}
@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("早上好!");
    }
}
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");
	}
}

2、 wsimport http://192.168.114.10:99998/ws/jobService?WSDL

3、打jar包
命令列: jar -cvf jobService.jar ./cn

public class Test {
	/*
	* 測試通過實現介面的webservice釋出方式
	 */
public static void main(String[] args) {
	JobServiceImplService ws=new JobServiceImplService();
	JobService jobServiceImplPort = ws.getJobServiceImplPort();
	String jobs = jobServiceImplPort.getJob();
	//"JEE研發工程師|Android研發工程師|資料庫工程師|前端工程師|測試工程師|運維工程師"
	String[] jobArray=jobs.split("\\|");
	System.out.println(jobArray[2]);
	System.out.println(jobArray[0]);
	System.out.println(jobArray[3]);
    }
}

四、遠端訪問天氣預報服務(jsp+ajax+servlet+webservice)

1、webservice 客戶端訪問的方式
① java程式碼來訪問
② ajax 方式非同步載入webservice

2、通過 ajax 非同步載入天氣資訊實現步驟:
① 瞭解遠端第三方的天氣預報webservice服務
② wsimport 生成本地代理
③ 準備一個index.jsp頁面,顯示城市資訊,下拉城市顯示天氣資訊

<html>
  <head>
  <script type="text/javascript" src="jquery-1.8.2.js"></script>
  </head>
  
  <body>
   <select id="province">
   <option value="31124">廣東省</option>
   </select>
   <select id="city">
   <option value="2350">廣州</option>
   <option value="2419">深圳</option>
   <option value="2351">東莞</option>
   </select>
   <hr/>
   <span>XXXX</span>
   <script type="text/javascript">
     $("#city").change(function(){
       var city=$("#city option:selected").val();
       $.post("weatherServlet",{"city":city},function(backdata){
         $("span").text(backdata).css("color","blue");
       });
     });
   </script>
  </body>
</html>

④ 準備一個weatherServlet,通過它來訪問webservcie

public class WeatherServlet extends HttpServlet {
	private WeatherWS ws;
	public WeatherServlet() {
		super();
	}
	public void destroy() {
		super.destroy(); // Just puts "destroy" string in log
		// Put your code here
	}
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		this.doPost(request, response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		String cityCode=request.getParameter("city");
		System.out.println("獲取城市的id"+cityCode);
		//通過webservice獲取遠端的天氣預報資訊
		WeatherWSSoap weatherWSSoap = ws.getWeatherWSSoap();
		List<String> weathers = weatherWSSoap.getWeather(cityCode, "").getString();
		String weather=weathers.get(8);//取得溫度資訊
		//把結果回顯給頁面
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter printWriter=response.getWriter();
		printWriter.write(weather);
		printWriter.flush();
		printWriter.close();	
	}

	public void init() throws ServletException {
		// Put your code here
		ws=new WeatherWS();
	}
}

⑤ Servlet要在web.xml註冊

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
  <servlet>
    <description>This is the description of my J2EE component</description>
    <display-name>This is the display name of my J2EE component</display-name>
    <servlet-name>WeatherServlet</servlet-name>
    <servlet-class>cn.it.ws.weather.WeatherServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>WeatherServlet</servlet-name>
    <url-pattern>/weatherServlet</url-pattern>
  </servlet-mapping>

</web-app>

五、CXF框架

1、為了解決上述方法通過Jdk實現webservice的不足: 希望tomcat啟動時,webservice服務能夠開啟 ,最好與Spring整合;希望有一個webservice的服務列表 ,通過Webservice框架來實現(axis2、xfire……),可以使用CXF框架,釋出webservice服務,並使用客戶端遠端訪問webservice

2、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

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

4、需求:開發語言排行描述服務
① 伺服器端

@WebService(serviceName="languageManager")
public interface LanguageService {
	public @WebResult(name="language")String getLanguage(@WebParam(name="position")int position);
}
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 訪問流程:
	 *    - 檢測本地代理描述的wsdl是否與服務端的wsdl一致,俗稱為握手
	 *    - 通過soap協議實現通訊,採用的是post請求,資料封裝在滿足soap規約的xml中
	 *    - 返回資料 同樣採用的是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");
	}
}

② 客戶端

public class Test {
  /*
  * 測試有CXF框架釋出的webservice服務
   */
	public static void main(String[] args) {
		LanguageManager ws=new LanguageManager();
		LanguageService languageServicePort = ws.getLanguageServicePort();
		System.out.println(languageServicePort.getLanguage(1));
	}
}

5、Spring+CXF整合來管理webservice實現步驟
前面的服務釋出包括建立服務類都是硬編碼的方式,是否可以使用配置的方式來發布服務類呢?答案是肯定的,這就要同Spring集成了。由於cxf的專案已經集成了Spring(自帶了Spring lib),所以CXF的服務都是在Spring的配置檔案中完成的,並且我們需要把專案釋出到tomcat中
① 新增cxf.jar 包(集成了Spring.jar、servlet.jar )、spring.jar包、servlet.jar 包
【新增Spring.jar:右擊專案>Myeclipse>Project Facets[Capablilities]>Install Spring Facet】
② 編寫業務類,通過CXF來發布webservice

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;
	}
}
@WebService(serviceName="EmployeeService")
public interface EmployeeManager {
	public abstract void add(@WebParam(name="employee")Employee employee);
	public abstract @WebResult(name="employees")List<Employee> query();
}
/*
* 員工管理的業務實現類
 */
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;
	}
}

③ 新增一個CXF請求的 Servlet,用來處理webservice的請求 ,過濾的地址:/ws/*
④ 配置Spring的配置檔案:applicationContext.xml ,把cxf的bean在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>

⑤ 在web.xml中配置 CXF的Servlet,新增spring的監聽

<?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>

⑥ 通過wsimport生成本地代理,訪問webservice

6、webservice測試工具
Launch SOAP Web Services Exprlorer>WSDL Page>WSDL Main>輸入地址