轉載請注明出處:http://www.cnblogs.com/Starshot/p/7050084.html
Soap即簡單對象訪問協議,也可理解為一種用於程序之間通訊的規范,它主要基於XML和http,也正因為基於XML和http,所以這個協議具有很強的通用性,能夠很好地實現不同語言平台之間的交流通訊。缺點是相對比較重量級。
Java的Soap框架有很多,例如xfire,CXF。說到soap不得不提一下rest,因為這些概念很容易弄混。
rest是一種結構風格,而實現了rest風格的程序設計就叫做restful。它提倡更加輕量級、無狀態、自描述,更充分地利用http本身的特性,例如get,post,put,delete,以獲得更加高效的性能,使交互更加簡潔易懂。例如要獲取圖書集合中的某本書AAA,可以直接通過uri:/books/AAA來表示。
而soap則都是通過post來請求的,沒有充分利用http的其它方法,僅將http作為傳輸協議來使用,而具體需要獲取的資源信息則包含在post的xml報文中。
需要注意的是,rest是一種風格,它不限制於某個程序某個框架。例如CXF框架,它既可以實現rest風格的webService,也可以實現SOAP規范的webService。例如在我另一篇博文中的CXF簡單例子(http://www.cnblogs.com/Starshot/p/6889751.html),就可以看做是rest風格的webService。
現在就先以JAX-WS這個輕量級的框架 (后面再和Spring合在一起) 來實現一個soap規范的超簡單的webService。
首先建一個WebService的web工程,這個作為服務的提供方。然后建一個HelloService類,如下所示:

然后類的代碼如下:
package com.webService; import javax.jws.WebService; import javax.xml.ws.Endpoint; @WebService public class HelloService { public String sayIt(String str){ return "say it:"+str; } public static void main(String[] args) { Endpoint.publish("http://localhost:9009/hello/HelloService", new HelloService()); System.out.println("publish done!"); } }
是不是很簡單,是不是很驚喜,然后直接執行,出現publish done!然后打開瀏覽器,輸入http://localhost:9009/hello/HelloService?wsdl,出現wsdl文件信息的話,就算是成功了。
接下來再建一個客戶端工程,如下所示:

這個時候需要生成wsdl的客戶端,對這工程點擊右鍵,然后新建WebService client:

點下一步,輸入剛剛在瀏覽器輸入的地址:

然后再點擊下一步設置了代碼的路徑之后按確定就可以了,成功之后如下圖所示:

其中com.webService里面的就是客戶端程序了。然后再如上圖新建一個測試類test1,內容如下:
package com.test; import java.rmi.RemoteException; import javax.xml.rpc.ServiceException; import com.webService.HelloService; import com.webService.HelloServiceProxy; import com.webService.HelloServiceServiceLocator; public class test1 { public static void main(String[] args) throws ServiceException, RemoteException { HelloService hs=new HelloServiceProxy(); System.out.println(hs.sayIt("Yohoo!!")); } }
執行,該程序,控制台輸出:Yohoo!!,這就表示成功了。
通過查看客戶端代碼可以知道,HelloServiceProxy,HelloServiceServiceLocator,HelloServicePortBindingStub三個類其實都可以用來調用服務。而所有類最終都是通過HelloServicePortBindingStub類中的sayIt方法來實現的,HelloServiceProxy和HelloServiceServiceLocator其實是對HelloServicePortBindingStub進行了進一步的加工,這也是代理模式的一種體現。
再然后,上面這種方式發布服務雖然簡單,但在實際應用中肯定不是這樣子發布服務的,實際肯定是要發布在web中的。JAX-WS和Spring結合起來發布一個WebService服務:
首先在原來的WebServiec工程加入以下jar包:
commons-logging-1.0.4.jar
gmbal-api-only.jar
ha-api.jar
jaxb-impl.jar
jaxws-api.jar
jaxws-rt.jar
jaxws-spring-1.8.jar
management-api.jar
policy.jar
spring-beans-3.2.14.RELEASE.jar
spring-context-3.2.14.RELEASE.jar
spring-core-3.2.14.RELEASE.jar
spring-expression-3.2.14.RELEASE.jar
spring-web-3.2.14.RELEASE.jar
stax-ex.jar
streambuffer.jar
xbean-spring-3.0.jar
因為涉及jar包比較多,如果有需要的話,可以留下郵箱,我發過去。
然后建一個SpeakingService類,Component注解是表示這個類將被spring容器管理,如下所示,
package com.webService; import javax.jws.WebService; import org.springframework.stereotype.Component; @Component @WebService public class SpeakingService { public String speak(String content) { return "speaking:"+content; } }
然后在WEB-INF下建web.xml文件,內容如下:
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>jwsService</servlet-name> <servlet-class> com.sun.xml.ws.transport.http.servlet.WSSpringServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>jwsService</servlet-name> <url-pattern>/SpeakingService</url-pattern> </servlet-mapping>
</web-app>
然后在src路徑下建立applicationContext.xml文件,內容如下:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ws="http://jax-ws.dev.java.net/spring/core" xmlns:wss="http://jax-ws.dev.java.net/spring/servlet" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://jax-ws.dev.java.net/spring/core http://jax-ws.dev.java.net/spring/core.xsd http://jax-ws.dev.java.net/spring/servlet http://jax-ws.dev.java.net/spring/servlet.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd "> <context:component-scan base-package="*"/> <wss:binding url="/SpeakingService"> <wss:service> <ws:service bean="#speakingService" /> </wss:service> </wss:binding> </beans>
這里有個細節要注意的是<ws:service bean="#speakingService" />這里的speakingService首字母記得要小寫,雖然原來的類名是大寫開頭,但是默認加載進spring容器之后,bean的id就是一小寫開頭了。
最后就是用tomcat將這個工程啟動就可以了,訪問的ip和端口以及資源名稱就以tomcat容器的設定為准了。生成客戶端的方法和剛開始說的一樣。
如果有問題,歡迎指出交流。
轉載請注明出處:http://www.cnblogs.com/Starshot/p/7050084.html
