當大型需求被數個公司分割開來,各公司系統相互交換數據的問題就會接踵而來。
畢竟是多家不同的公司的產品,研發開發語言、采用技術框架基本上是百花齊放。
怎樣讓自家系統提供的服務具有跨平台、跨語言、跨各種防火牆,讓其他公司的研發使用起來沒障礙並且爽呢?
進過前期的技術調研和實踐,最終將目光放在了輕量級 Web Services 服務上面。
公司自己實現 Web Services 服務框架肯定是不現實的,如果你公司有一群熱愛技術的大牛、有一顆想造輪子的匠心,有老總的支持,還是可以放手一戰的。
目前已有的 Web Services 開發框架有: Axis、Axis2、Xfire、CXF、JAX-WS。
除了 JAX-WS 為 JDK 1.6 發布的的 Web Services 開發框架以外,其余的都是第三方開源框架。
其中 Axis 和 XFire 隨著技術更新和發展已經慢慢的談出了人們的視線,並且官方已經有很長時間沒有更新,這裡暫且不表。
CXF是Apache旗下一個重磅的SOA簡易框架,它實現了ESB(企業服務總線)。
CXF 原型來源與 XFire + Client, 就像 Struts2 來自 WebWork 一樣,當然你也能預言到 XFire 的命運會和 WebWork 一樣,會淡出開發者的視線。
Axis2 是 Apache 下的一個重量級 Web Services框架,准確說它是一個Web Services / SOAP / WSDL 的引擎,是 Web Services 框架的集大成者。
Axis2 不但能制作和發布WebService,而且可以生成Java和其他語言版WebService客戶端和服務端代碼。這是它的優勢所在。
豐滿意味著臃腫和龐大,這樣的優勢也不可避免的導致了Axis2的復雜性,聽使用過她的人,它所依賴的包數量和大小都是很驚人的,打包部署發布很麻煩。
源於對第三方開源框架的恐懼和顫抖,結合自身公司的業務復雜度,技術團隊一致選定 JDK JAX-WS 作為公司的 Web Services 框架。
上述參考出處:
http://zhidao.baidu.com/link?url=H_CijOzBSzpLnZ
http://baike.baidu.com/link?url=OHYozkeWQkpZDmnKeDk9Ja
我這裡的說的無 MVC 框架指的是沒有使用任何像 Struts/Spring MVC/WebWork....這些東西,Java EE 項目最純真的 Servlet 時代。
在 main 函數中靜態方式發布這裡就不提了,確實有點 low,咱需要 Web Services 服務和 web 項目一起啟動起來,同呼吸共命運。
main 靜態發布方式參考:http://www.xuebuyuan.com/1955910.html
<dependency> <groupId>com.sun.xml.ws</groupId> <artifactId>jaxws-rt</artifactId> <version>2.2.10</version> </dependency>
如果是非 mavn的傳統項目, 需要的 jar (大概 5M)
項目包結構
@WebService @SOAPBinding(style = SOAPBinding.Style.RPC) public interface MyFirstWebService { /** * 執行測試的WebService方法(有參) */ @WebMethod String sayHi(@WebParam(name = "name") String name); }
@WebService(endpointInterface = "com.rambo.cwe.jws.inter.MyFirstWebService") @SOAPBinding(style = SOAPBinding.Style.RPC) public class MyFirstWebServiceImpl implements MyFirstWebService { public String sayHi(String name) { return "Hi, " + name + "! "; } }
<listener> <listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class> </listener> <servlet> <servlet-name>MyFirstWebService</servlet-name> <servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>MyFirstWebService</servlet-name> <url-pattern>/services/sayHi</url-pattern> </servlet-mapping>
<?xml version="1.0" encoding="UTF-8"?> <endpoints xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime" version="2.0"> <endpoint name="myFirstWebService" implementation="com.rambo.cwe.jws.impl.MyFirstWebServiceImpl" url-pattern="/services/sayHi"/> </endpoints>
注意服務配置文件中的 url-pattern 和 servlet 中的 url-pattern 是一致的。
通過上面的4步的操作,啟動 web 項目吧,不出什麼意外的話,啟動 web 容器打印日志是這樣。
浏覽器訪問 http://localhost:5050/cwe/services/sayHi
在 Spring 中集成相當簡單,分分鐘配置集成。
<dependency> <groupId>org.springframework.ws</groupId> <artifactId>spring-ws-core</artifactId> <version>2.3.0.RELEASE</version> </dependency>
<bean class="org.springframework.remoting.jaxws.SimpleJaxWsServiceExporter"> <property name="baseAddress" value="http://localhost:8089/services/"/> </bean>
地址你隨意,配置為和 web 項目一致也沒問題。
大體的意思是你得讓 Spring 知道有這樣一個服務實現類。
如果你比較傳統,可以配置在 Spring-***.xml 中,像這樣
<bean id="myFirstWebServiceImpl" class="com.rambo.cwe.jws.impl.MyFirstWebServiceImpl"> ... </bean>
當然你也可以,使用注解,像這樣
簡單的三步之後,把你的 web 容器啟動起來吧,Web Services 服務就發布成功了。
服務端編寫好之後,使用 JDk 自帶的 wsimport 工具生成客戶端代理類。
wsimport 只需要指定 url 就能生成 java 調用的客戶端,你完全不用去了解這個 WebServer 服務是用什麼語言編寫的。
關於 wsimport 生成代理類:http://blog.csdn.net/aqsunkai/article/details/51711087
生成客戶端代理類之後,只需要兩行代碼就能,實現 Web Services 服務的調用。
wsimport -s f: http://localhost:5050/cwe/services/sayHi?wsdl
生成的代理類(生成姿勢多種多樣,自行參考上面常用參數,沒有標准只有最適合):
將代理類放入客戶端項目,調用代碼
MyFirstWebServiceImplService service = MyFirstWebServiceImplService(); MyFirstWebService implPort = service.getMyFirstWebServiceImplPort(); System.out.println(implPort.sayHi("Orson"));
其實我一直想嘗試,不往客戶端添加任何代碼,調用 Web Services 服務,很遺憾沒能成功。
最接近的的是,在客戶端放入服務端的接口類,代碼可以這樣寫。
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"));
自行定義連接地址、服務名稱、、端口名稱,生成服務實例進行訪問,代碼完全沒有使用代理類那樣清晰。
等下次,你們公司需要給其他公司提供服務時,只需要編寫好 Web Services,抽象好接口,撸好實現層。
直接甩一個地址給其他公司,順便可以把我這篇博客地址發過去,然後整個世界就安靜了。