當大型需求被數個公司分割開來,各公司系統互相交換資料的問題就會接踵而來。畢竟是多家不同的公司的産品,研發開發語言、采用技術架構基本上是百花齊放。怎樣讓自家系統提供的服務具有跨平台、跨語言、跨各種防火牆,讓其他公司的研發用起來沒障礙和爽呢?進過前期的技術調研和實踐,最終将目光放在了輕量級 webservice 服務上面
1. webservice 服務技術的關鍵點xml:
做為 webservice 的基本資料表示,特點即容易組織和分析,而且又與開發平台無關。
soap: 做為 webservice 的傳輸協定,特定能運作在任何傳輸協定(tcp/udp..)上面,将程式中的對象編碼為 xml 的規則,執行遠端調用。
wsdl: 做為描述 webservice 的語言,你能很清晰的知道提供的服務是什麼、入參、傳回的資料,機器和人都很容器進行閱讀。
公司自己實作 webservice 服務鐵定不現實,如果你公司有一群熱愛技術的大牛、有一顆想造輪子的匠心,有老總的支援,還是可以放手一戰的。
目前已有的 webservice 開發架構有: axis、axis2、xfire、cxf、jax-ws。
除了 jax-ws 為 jdk 1.6 釋出的的 webservice 開發架構以外,其餘的都是第三方開源架構。
其中 axis 和 xfire 随着技術更新和發展已經慢慢的談出了人們的視線,并且官方已經有很長時間沒有更新,這裡暫且不表。
cxf是apache旗下一個重磅的soa簡易架構,它實作了esb(企業服務總線)。
cxf 原型來源與 xfire + client, 就像 struts2 來自 webwork 一樣,當讓你也能預言到 xfire 的命運會和 webwork 一樣,會淡出開發者的視線。
axis2 是 apache 下的一個重量級 webservice 架構,準确說它是一個web services / soap / wsdl 的引擎,是 webservice 架構的集大成者。
axis2 不但能制作和釋出webservice,而且可以生成java和其他語言版webservice用戶端和服務端代碼。這是它的優勢所在。
豐滿意味着臃腫和龐大,不可避免的導緻了axis2的複雜性,聽使用過她的人,它所依賴的包數量和大小都是很驚人的,打包部署釋出很麻煩。
源于對第三方開源架構的恐懼和顫抖,結合自身公司的業務複雜度,技術團隊一緻標明 jdk jax-ws 作為公司的 webservice 架構。
我這裡的說的無 mvc 架構指的是沒有使用任何像 struts/spring mvc/webwork....這些東西,java ee 項目最純真的 servlet 時代。
在 main 函數中靜态方式防部的方式這裡就不提了,咱需要 webserver 服務和 web 項目一起啟動起來,同呼吸共命運。
<dependency> <groupid>com.sun.xml.ws</groupid> <artifactid>jaxws-rt</artifactid> <version>2.2.10</version> </dependency>
如果是jar包方式的話,
需要如下jar。
完整的項目結構如下:
web.xml配置
注意服務配置檔案中的 url-pattern 和 servlet 中的 url-pattern 是一緻的。通過上面的4步的操作,啟動 web 項目吧,不出什麼意外的話,啟動 web 容器列印日志是這樣。
大體的想法是你得讓 spring 知道有這樣一個服務實作類。如果你比較傳統,可以配置在 spring-***.xml 中,像這樣 ... 當然你也可以,使用注解,像這樣
服務端編寫好之後,使用 jdk 自帶的 wsimport 工具生成用戶端代理類。
wsimport 隻需要指定 url 就能生成 java 調用的用戶端,你完全不用去了解這個 webserver 服務是用什麼語言編寫的。
生成用戶端代理類之後,隻需要兩行代碼就能,實作 webserver 服務的調用。
wsimport -s f: http://localhost:5050/cwe/services/sayhi?wsdl
wsimport 常用參數參考
參數 說明
-p 定義用戶端生成類的包名稱
-s 指定用戶端執行類的源檔案存放目錄
-d 指定用戶端執行類的class檔案的存放目錄
-keep 表示生成用戶端執行類的源代碼
-b 指定jaxws/jaxb綁定檔案或額外的schemas
-extension 使用擴充來支援soap1.2
将代理類放入用戶端,調用代碼
myfirstwebserviceimplservice service = myfirstwebserviceimplservice; myfirstwebservice implport = service.getmyfirstwebserviceimplport; system.out.println(implport.sayhi("orson"));
其實我一直想嘗試,不再用戶端添加任何類調用 webserver 服務,很遺憾沒能成功。
最接近的的是,在用戶端放入服務端的 接口類,代碼可以這樣寫。
url url = new url("http://localhost:5050/cwe/services/sayhi?wsdl"); qname servicename = new qname("http://impl.jws.cwe.rambo.com/", "myfirstwebserviceimplservice"); qname portname = new qname("http://impl.jws.cwe.rambo.com/", "myfirstwebserviceimplport"); service service = service.create(url,servicename); myfirstwebservice serviceport = service.getport(portname,myfirstwebservice.class); system.out.println(serviceport.sayhi("orson"));
自行定義連接配接位址、服務名稱、、端口名稱,生成服務執行個體進行通路,代碼完全沒有代理類那樣清晰。