原文地址:http://my.oschina.net/huangyong/blog/286155
Web Service,即“Web 服務”,簡寫爲 WS,從字面上理解,它其實就是“基於 Web 的服務”。而服務卻是雙方的,有服務需求方,就有服務提供方。服務提供方對外發布服務,服務需求方調用服務提供方所發佈的服務。其實也就是這些了,沒有多少高大上的東西。
本文將從實戰的角度,描述使用 Java 開發 WS 的工具及其使用過程。
如果說得再專業一點,WS 其實就是建立在 HTTP 協議上實現異構系統通訊的工具。沒錯!WS 說白了還是基於 HTTP 協議的,也就是說,數據是通過 HTTP 進行傳輸的。
自從有了 WS,異構系統之間的通訊不再是遙不可及的夢想。比如:可在 PHP 系統中調用 Java 系統對外發布的 WS,獲取 Java 系統中的數據,或者把數據推送到 Java 系統中。
如果您想了解更多關於 WS 的那些概念與術語,可以看看下面的百度百科:
http://baike.baidu.com/view/67105.htm
今天我想與大家分享的主題是,如何在 Java 中發佈與調用 WS?希望本文能夠對您有所幫助!
1. 使用 JDK 發佈 WS
第一步:您要做的第一件事情就是,寫一個服務接口。
1 |
package demo.ws.soap_jdk; |
3 |
import javax.jws.WebService; |
6 |
public interface HelloService
{ |
8 |
String
say(String name); |
在接口上放一個 WebService
註解,說明該接口是一個
WS 接口(稱爲“Endpoint,端點”),其中的方法是 WS 方法(稱爲“Operation,操作”)。
第二步:實現這個 WS 接口,在實現類中完成具體業務邏輯,爲了簡單,我們還是寫一個 Hello World 意思一下吧。
01 |
package demo.ws.soap_jdk; |
03 |
import javax.jws.WebService; |
06 |
serviceName
= "HelloService" , |
07 |
portName
= "HelloServicePort" , |
08 |
endpointInterface
= "demo.ws.soap_jdk.HelloService" |
10 |
public class HelloServiceImpl implements HelloService
{ |
12 |
public String
say(String name) { |
13 |
return "hello
" +
name; |
第三步:寫一個 Server 類,用於發佈 WS,直接使用 JDK 提供的工具即可實現。
01 |
package demo.ws.soap_jdk; |
03 |
import javax.xml.ws.Endpoint; |
07 |
public static void main(String[]
args) { |
08 |
String
address = "http://localhost:8080/ws/soap/hello" ; |
09 |
HelloService
helloService = new HelloServiceImpl(); |
11 |
Endpoint.publish(address,
helloService); |
12 |
System.out.println( "ws
is published" ); |
只需使用 JDK 提供的 javax.xml.ws.Endpoint
即可發佈
WS,只需提供一個 WS 的地址(address),還需提供一個服務實例(helloService)。
現在您就可以運行 Server 類的 main 方法了,會在控制檯裏看到“ws is published”的提示,此時恭喜您,WS 已成功發佈了!
第四步:打開您的瀏覽器,在地址欄中輸入以下地址:
http://localhost:8080/ws/soap/hello?wsdl
注意:以上地址後面有一個 ?wsdl
後綴,在 Server
類中的
address 裏卻沒有這個後綴。此時,在瀏覽器中會看到如下 XML 文檔:
當看到這份 WSDL 文檔時,也就意味着,您發佈的 WS 服務現在可以被別人使用了。
2. 通過客戶端調用 WS
第一步:使用 JDK 提供的命令行工具生成 WS 客戶端 jar 包。
JDK 安裝目錄下有個 bin 目錄,裏面存放了大量的命令行工具,只要您的 Path
環境變量指向了該路徑,就能在命令控制檯上使用
JDK 提供的相關命令。
其中,有一個名爲 wsimport
的命令行工具,正是用來通過
WSDL 生成 WS 客戶端代碼的,您只需要輸入以下命令即可:
對以上三行命令解釋如下:
- 第一行:通過 WSDL 地址生成 class 文件
- 第二行:通過 jar 命令將若干 class 文件壓縮爲一個 jar 包
- 第三行:刪除生成的 class 文件(刪除根目錄即可)
最終您將會得到一份名爲 client.jar
的
jar 包,將這個 jar 包配置到您的 classpath 中,方便在下面的代碼中使用其中的類。
技巧:可以將以上三行命令放入一個 bat 文件中,在 Windows 中雙擊即可運行。
第二步:寫一個 Client 類,用於調用 WS,需要使用上一步生成的 WS 客戶端 jar 包。
01 |
package demo.ws.soap_jdk; |
05 |
public static void main(String[]
args) { |
06 |
HelloService_Service
service = new HelloService_Service(); |
08 |
HelloService
helloService = service.getHelloServicePort(); |
09 |
String
result = helloService.say( "world" ); |
10 |
System.out.println(result); |
以上這段代碼稍微有點怪異,其中 HelloService_Service
是
jar 包中類,可以將其理解爲 WS 的工廠類,通過它可以生成具體的 WS 接口,比如,調用 service.getHelloServicePort()
方法,就獲取了一個 HelloService
實例,正是通過這個實例來調用其中的方法。
運行 Client 類的 main 方法,就會看到您所期望的結果“hello world”了,不妨親自嘗試一下吧。
可見,這是一個典型的“代理模式”應用場景,您實際是面向代理對象來調用 WS 的,並且這是一種“靜態代理”,下面我們來談談,如何使用“動態代理”的方式來調用 WS?
其實 JDK 已經具備了動態代理的功能,對於 WS 而言,JDK 同樣也提供了很好的工具,就像下面這段代碼那樣:
01 |
package demo.ws.soap_jdk; |
04 |
import javax.xml.namespace.QName; |
05 |
import javax.xml.ws.Service; |
07 |
public class DynamicClient
{ |
09 |
public static void main(String[]
args) { |
11 |
URL
wsdl = new URL( "http://localhost:8080/ws/soap/hello?wsdl" ); |
12 |
QName
serviceName = new QName( "http://soap_jdk.ws.demo/" , "HelloService" ); |
13 |
QName
portName = new QName( "http://soap_jdk.ws.demo/" , "HelloServicePort" ); |
14 |
Service
service = Service.create(wsdl, serviceName); |
16 |
HelloService
helloService = service.getPort(portName, HelloService. class ); |
17 |
String
result = helloService.say( "world" ); |
18 |
System.out.println(result); |
19 |
} catch (Exception
e) { |
此時,只需在本地提供一個 HelloService 的接口,無需 client.jar,直接面向 WSDL 編程,只不過您需要分別定義出 serviceName
與 portName
這兩個東西,最後才能調用
JDK 提供的 javax.xml.ws.Service
類生成
service 對象,它同樣是一個工廠對象,通過該工廠對象獲取我們需要的 HelloService
實例。貌似這種方式也不是特別動態,畢竟
HelloService 接口還是需要自行提供的。
3. 總結
通過本文,您可以瞭解到,不僅可以使用 JDK 發佈 WS,也可以使用 JDK 調用 WS,這一切都是那麼的簡單而自然。但需要注意的是,這個特性是從 JDK 6 纔開始提供的,如果您還在使用 JDK 5 或更低的版本,那就很遺憾了,您不得不使用以下工具來發布與調用 WS,它們分別是:
當然,發佈與調用 WS 的工具不僅僅只有以上這些,而是它們是 Java 世界中最優秀的 WS 開源項目。
本文講述的 WS 其實是一種 Java 規範,名爲 JAX-WS
(JSR-224),全稱
Java API for XML-Based Web Services,可以將規範理解爲官方定義的一系列接口。
JAX-WS 有一個官方實現,就是上面提到的 JAX-WS RI,它是 Oracle 公司提供的實現,而 Apache 旗下的 Axis 與 CXF 也同樣實現了該規範。Axis 相對而言更加老牌一些,而 CXF 的前世就是 XFire,它是一款著名的 WS 框架,擅長與 Spring 集成。
從本質上講,JAX-WS 是基於 SOAP 的,而 SOAP 的全稱是 Simple Object Access Protocol(簡單對象訪問協議),雖然名稱裏帶有“簡單”二字,其實並不簡單,不相信您可以百度一下。
爲了讓 WS 的開發與使用變得更加簡單、更加輕量級,於是出現了另一種風格的 WS,名爲 JAX-RS
(JSR-339),全稱
Java API for RESTful Web Services,同樣也是一種規範,同樣也有若干實現,它們分別是:
其中,Jersey 是 Oracle 官方提供的實現,Restlet 是最老牌的實現,RESTEasy 是 JBoss 公司提供的實現,CXF 是 Apache 提供的實現(上文已做介紹)。
可見,CXF 不僅用於開發基於 SOAP 的 WS,同樣也適用於開發基於 REST 的 WS,這麼好的框架我們怎能錯過?
如何使用 CXF 簡化我們的 WS 開發?我們下期再見!