閑來無事,根據教學視訊學下WS,做下簡單的記錄…
現行的 WS主要有 SOAP XML 、axis2、xfire、CXF 等…
不管是哪種接口,哪種平台基于哪種語言開發的WS 都嚴格按照wsdl标準和soap協定。
以下的學習 主要都是基于注解的形式開發,jdk1.6,開發工具eclipse
一、第一個簡單的示例
首先建立一個WS項目。
代碼:
Java代碼
- //定義接口
- @WebService(targetNamespace="com.trylin.ws.service")
- public interface ITest {
- public int add(int a,int b);
- public int minus(int a,int b);
- }
- //定義實作類
- @WebService(endpointInter)
- public class TestImpl implements ITest{
- public int add(int a, int b) {
- return a+b;
- }
- public int minus(int a, int b) {
- return a-b;
- }
- }
- //開啟服務
publicstaticvoid main(String[] args) {
String address = "http://localhost:8888/WS";
Endpoint.publish(address, new TestImpl());
}
驗證服務
打開浏覽器,輸入http://localhost:8888/WS?wsdl 顯示釋出服務的wsdl
代碼解釋
上述代碼中實作了一個簡單的WS的釋出。
首先定義一個接口和實作類 ITest,TestImpl
然後加入@WebService 注解。
targetNamespace 屬性表示釋出後生成WSDL檔案的命名空間(預設值:目前類的包路徑),對應namespace
<import namespace="http://com.trylin.ws.service/" location="http://localhost:8888/WS?wsdl=1"/>
這裡有個小細節,注意到這個namespace是不是覺得有點别扭呢,先想想包命名原則,下面生成用戶端調用的時候,簡單再說明一下。
endpointInterface 屬性表示實作的接口
Endpoint.publish(address, new TestImpl());
根據位址 和實作類,将接口釋出。
釋出後的WS位址就是 address ,可以直接通路,在address後加入 ?wsdl 可以檢視接口釋出後的wsdl。
用戶端調用
上面就算是釋出了一個簡單的WS,簡單吧,然後用戶端怎麼調用呢?
這裡就用到了jdk 1.6自帶的 wsimport指令
打開cmd指令視窗 ,輸入 wsimport, 如圖:(ps:請保證在你運作電腦的jdk環境變量設定正确,沒有jdk配置環境變量,百度下)
簡單的介紹幾個主要的指令
-d 指明生成WS用戶端檔案本地存放目錄
-verbose 檢視生成的詳細資訊(生成日志)
-p 指定ws用戶端生成檔案的包名(預設按照 @webService定義的命名空間)
-keep 是否生成源檔案(加 表示生成的檔案中 包含java和 class ,不加隻有class)
建立本地用戶端存放目錄
D:/webservice/test
(記得開服務哦運作上面的main)
在cmd中 輸入 wsimport -d D:\webservice\test -keep -verbose http://localhost:8888/WS?wsdl
generating code... 表示建立的java檔案
compiling code... 表示編譯java檔案
上面不是說過 wsdl上的命名空間有點問題,這下看日志有看出來嗎?哈哈,應該有發現吧,生成的java源檔案的目錄是不是和我們在服務端的源檔案目錄剛好颠倒了呢。我也是看到這裡才發現這個問題的。簡單的說下我個人對這個問題的想法吧。
Java關于包,有個簡單的命名原則,就是按照域名反向命名,比如 baidu.com 包名就叫com.baidu。我們生成的用戶端檔案是根據wsdl生成的,包名是根據wsdl中的namespace定義,隻不過會将namespace視為一個域名,然後反向生成用戶端類的包名。我在第一個示例中的接口中定義了@WebService(targetNamespace="com.trylin.ws.service") 按照反向,生成的包名就是 service.ws.trylin.com 然後就出現了我們剛才的用戶端檔案和服務端檔案包名相反的現象了。
這個隻是我個人的一個憑空猜想,沒什麼依據可言,呵呵。
OK,按照我上面的了解,我把命名空間 反向定義 service.ws.trylin.com
重新生成用戶端。
然後再建立一個新的clinet項目,把生成的用戶端複制到項目中,建立用戶端測試類。
Java代碼
- public class ITestCase {
- @Test
- public void testClient1() throws Exception{
- URL url = new URL("http://localhost:8888/WS?wsdl"); //wsdl路徑
- //可以從 産生的wsdl中definitions 節點屬性中 找到 targetNamespace 和 serviceName
- String targetNamespace = "http://impl.service.ws.trylin.com/";//WS指向命名空間
- String serviceName = "TestImplService";//WS釋出服務名稱
- QName qname = new QName(targetNamespace, serviceName);
- Service service = Service.create(url,qname);
- ITest test = service.getPort(ITest.class);
- System.out.println(test.add(1, 2));
- }
- @Test
- public void testClient2(){
- TestImplService service = new TestImplService();
- ITest test = service.getTestImplPort();
- System.out.println(test.add(3, 2));
- }
- }
兩種調用方式都可以,隻是第二種方式看上去更加簡潔。
可以看下 第二種方式的 TestImplService代碼 ,其實隻是對第一種方式的部分封裝。
Java代碼
- public TestImplService() {
- super(TESTIMPLSERVICE_WSDL_LOCATION, new QName("http://impl.service.ws.trylin.com/", "TestImplService"));
- }
- @WebEndpoint(name = "TestImplPort")
- public ITest getTestImplPort() {
- return super.getPort(new QName("http://impl.service.ws.trylin.com/", "TestImplPort"), ITest.class);
- }
嗯 這樣一個簡單的WS就實作了,
WSDL和SOAP相關,待續…
我也是看教學視訊,邊看邊琢磨然後寫下,友善以後自己忘記的時候,可以參考下。
如果有大神看到這裡,還希望指點下錯誤的地方,或者提供下學習建議。