分分鍾帶你玩轉 Web Services【1】JAX-WS


   當大型需求被數個公司分割開來,各公司系統相互交換數據的問題就會接踵而來。

   畢竟是多家不同的公司的產品,研發開發語言、采用技術框架基本上是百花齊放。

   怎樣讓自家系統提供的服務具有跨平台、跨語言、跨各種防火牆,讓其他公司的研發使用起來沒障礙並且爽呢?

   進過前期的技術調研和實踐,最終將目光放在了輕量級 Web Services 服務上面。

 

   

 

1. Web Services 服務技術的關鍵點 

  • XML:     做為 Web Services 的基本數據表示,特點即容易組織和分析,而且又與開發平台和語言無關。
  • SOAP:   做為 Web Services 的通訊協議,基於 XML能運行在任何傳輸協議 HTTP/TCP/UDP/ 上面,將程序中的對象編碼為 XML 的規則,執行遠程調用。

    TCP/HTTP/UDP 傳輸協議可以理解為寄信時信封上的格式怎么寫,貼什么郵票,SOAP 通訊協議使用 HTTP 來發送XML 格式的信息。

  • WSDL:  做為描述 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

2. JAX-WS 服務端無 MVC 框架開發實踐

   我這里的說的無 MVC 框架指的是沒有使用任何像 Struts/Spring MVC/WebWork....這些東西,Java EE 項目最純真的 Servlet 時代。

   在 main 函數中靜態方式發布這里就不提了,確實有點 low,咱需要 Web Services 服務和 web 項目一起啟動起來,同呼吸共命運。

   main 靜態發布方式參考:http://www.xuebuyuan.com/1955910.html

  • a.maven 依賴

        <dependency>
            <groupId>com.sun.xml.ws</groupId>
            <artifactId>jaxws-rt</artifactId>
            <version>2.2.10</version>
        </dependency>

   如果是非 mavn的傳統項目, 需要的 jar (大概 5M)

  • b.服務類和實現類

   項目包結構

@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 + "! "; } }
  •  c.web 項目的起點,web.xml 的配置

 <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>
  •  d.服務配置文件 sun-jaxws.xml,放置到 WEB-INF

<?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

   示例項目: https://github.com/OrsonEx/cwe

3. JAX-WS 服務端與 Spring 集成開發實踐

   在 Spring 中集成相當簡單,分分鍾配置集成。

  • a.mavn 依賴需要添加的支持 jar(500K)

        <dependency>
            <groupId>org.springframework.ws</groupId>
            <artifactId>spring-ws-core</artifactId>
            <version>2.3.0.RELEASE</version>
        </dependency>
  • b.Spring Bean 添加 Web Services 服務支持

     <bean class="org.springframework.remoting.jaxws.SimpleJaxWsServiceExporter">
        <property name="baseAddress" value="http://localhost:8089/services/"/>
    </bean>

   地址你隨意,配置為和 web 項目一致也沒問題。

  • c.服務實現類 Bean 配置

   大體的意思是你得讓 Spring 知道有這樣一個服務實現類。

   如果你比較傳統,可以配置在 Spring-***.xml 中,像這樣

 <bean id="myFirstWebServiceImpl" class="com.rambo.cwe.jws.impl.MyFirstWebServiceImpl"> ... </bean>

   當然你也可以,使用注解,像這樣

   簡單的三步之后,把你的 web 容器啟動起來吧,Web Services 服務就發布成功了。

   實例工程:https://github.com/OrsonEx/sme-jws

4. 客戶端  JAX-WS 服務的調用

  服務端編寫好之后,使用 JDk 自帶的 wsimport 工具生成客戶端代理類。

  wsimport 只需要指定 url 就能生成 java 調用的客戶端,你完全不用去了解這個 WebServer 服務是用什么語言編寫的。

wsimport -s f:  http://localhost:5050/cwe/services/sayHi?wsdl

  wsimport 常用參數參考:

參數 說明
-p 定義客戶端生成類的包名稱
-s 指定客戶端執行類的源文件存放目錄
-d 指定客戶端執行類的class文件的存放目錄
-keep                                                      表示生成客戶端執行類的源代碼
-b 指定jaxws/jaxb綁定文件或額外的schemas
-extension 使用擴展來支持SOAP1.2

  補充: 關於 wsimport 生成代理類:http://blog.csdn.net/aqsunkai/article/details/51711087

  生成的代理類(生成姿勢多種多樣,自行參考上面常用參數,沒有標准只有最適合):

   將代理類放入客戶端項目,只需要兩行代碼就能實現 Web Services 服務的調用,如下

            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,抽象好接口,擼好實現層。

   直接甩一個地址給其他公司,順便可以把我這篇博客地址發過去,然后整個世界就安靜了。

   


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM