首先我們來談一下為什么需要學習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,來體驗一把:我們訪問
http://www.webxml.com.cn/zh_cn/index.aspx
進入到里邊
當我們輸入一個號碼,它就能夠查詢出我們的手機位置信息:
我們現在要做的就是將這個服務讓我們自己寫的應用程序中也可以調用,那怎么做呢???
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使用步驟如下:
- 創建 HttpClient 的實例
- 創建某種連接方法的實例,在這里是 GetMethod。在 GetMethod 的構造函數中傳入待連接的地址
- 配置要傳輸的參數,和消息頭信息
- 調用第一步中創建好的實例的 execute 方法來執行第二步中創建好的 method 實例
- 通過response讀取字符串
- 釋放連接。無論執行方法是否成功,都必須釋放連接
//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");
}
}
- 在類上添加@WebService注解,代表發布一個WebService服務
- 通過EndPoint(端點服務)發布一個webService。Endpoint也是jdk提供的一個專門用于發布服務的類,它的publish方法接收兩個參數,一個是本地的服務地址,二是提供服務的類。它位于javax.xml.ws.*包中。
- Endpoint.publish(String address, Object implementor) 靜態方法在給定地址處針對指定的實現者對象創建并發布端點
- 給類添加上@WebService注解后,類中所有的非靜態方法都將會對外公布
- 如果希望某個方法不對外公開,可以在方法上添加@WebMethod(exclude=true),阻止對外公開。
- 如果一個類上,被添加了@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/so... “ 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開發。非常好用...由于在網上見到的教程非常多,我就貼幾個我認為比較好的教程:
http://www.biliyu.com/article/986.html
http://blog.csdn.net/u010323023/article/details/52926051
http://blog.csdn.net/dreamfly88/article/details/52350370
獲取天氣預報
我們現在webservice就基本入門了,現在我想要做的就是自己寫的網站能夠拿到天氣預報的信息,于是我去
http://www.webxml.com.cn/zh_cn/index.aspx找到了天氣預報的服務
這個是天氣預報的WSDL地址:
http://ws.webxml.com.cn/WebServices/WeatherWS.asmx,那么我們只要解析該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文件。
轉自:
https://segmentfault.com/a/1190000013806509