使用Apache CXF开发SOAP Web服务
在上一篇文章中,我逐步介紹了使用apache CXF開發(fā)簡單的RESTFull服務(wù)的步驟。 在本文中,我將討論使用CXF開發(fā)SOAP Web服務(wù)。 在繼續(xù)前進(jìn)之前,讓我們了解構(gòu)成SOAP Web服務(wù)的一些概念/元素。
SOAP或簡單對象訪問協(xié)議
SOAP是一種協(xié)議,用于使用諸如http,smtp等應(yīng)用程序協(xié)議作為載體在網(wǎng)絡(luò)上交換基于XML的消息。 SOAP消息包含一個SOAP信封。 信封可以分為標(biāo)題和正文。 標(biāo)頭包含與上下文相關(guān)的定義(例如安全性),而主體包含實際的應(yīng)用程序數(shù)據(jù)。 典型的SOAP消息看起來像
<?xml version="1.0"?> <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"><soap:Header></soap:Header><soap:Body><m:GetStockPrice xmlns:m="http://www.example.org/stock"><m:StockName>IBM</m:StockName></m:GetStockPrice></soap:Body> </soap:Envelope>WSDL或Web服務(wù)描述語言
WSDL是基于標(biāo)準(zhǔn)的XML語言,用于描述Web服務(wù)。 WSDL完全描述了Web服務(wù)公開的公共接口,期望的參數(shù),返回的輸出結(jié)構(gòu)以及Web服務(wù)的位置。 WSDL將Web服務(wù)定義為能夠交換消息的通信端點(diǎn)的集合。 這些通信端點(diǎn)稱為端口。 端口由兩部分組成。
SOAP通訊樣式
存在兩種類型的溝通方式
SOAP Web服務(wù)使用的通信樣式在其WSDL中定義。
在文檔樣式中,作為肥皂主體一部分的應(yīng)用程序數(shù)據(jù)作為XML文檔發(fā)送。 可以通過也是WSDL一部分的xml模式來完全驗證該文檔。 由于XML可以按照服務(wù)開發(fā)人員的意愿包含結(jié)構(gòu),因此,編組和解編xml有效負(fù)載的責(zé)任在于提供者和使用者代碼的末尾。
顧名思義,以RPC風(fēng)格表示,使用者調(diào)用服務(wù)方法就像調(diào)用本地方法一樣。 為此,RPC消息包含使用者可以調(diào)用的公共接口方法的列表。 這些方法按名稱列為xml元素。 這些方法所需的方法參數(shù)構(gòu)成方法元素的子元素。 封送/取消封送的責(zé)任在于Web服務(wù)框架。 該框架包含其自己的封送/解封庫。 RPC樣式導(dǎo)致應(yīng)用程序代碼和Web服務(wù)框架之間的代碼緊密耦合,因此規(guī)范是創(chuàng)建文檔樣式服務(wù)。 掌握了關(guān)鍵概念之后,讓我們看一下如何使用Apache CXF編寫肥皂網(wǎng)絡(luò)服務(wù)的示例。
獲取本教程的源代碼
我已經(jīng)在SVN中提交了本教程的源文件。
- 您可以從以下網(wǎng)站下載該Web應(yīng)用程序: http : //subversion.assembla.com/svn/weblog4j/Weblog4jDemo/trunk
- 您可以從以下 網(wǎng)址 下載客戶端: http : //subversion.assembla.com/svn/weblog4j/DemoClient/trunk
注意:這兩個都是ItelliJ maven項目,因此您可以將它們直接導(dǎo)入到intelliJ IDE或?qū)⑽募謩訌?fù)制到其他IDE
創(chuàng)建一個struts2框架應(yīng)用程序以包含您的服務(wù)。
您可以使用任何MVC框架,但出于我自己的原因,我更喜歡struts2。 您可以在此處看到有關(guān)如何使用Eclipse在eclipse中創(chuàng)建空的struts2應(yīng)用程序的示例。
添加CXF依賴項
在您的項目POM中添加以下依賴項以下載CXF jar
<properties><cxf.version>2.5.0</cxf.version> </properties> <dependencies><!-- apache cxf --><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-frontend-jaxws</artifactId><version>${cxf.version}</version></dependency><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-frontend-jaxrs</artifactId><version>${cxf.version}</version></dependency><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-transports-http</artifactId><version>${cxf.version}</version></dependency> </dependencies>例如,讓我們創(chuàng)建一個簡單的書架網(wǎng)絡(luò)服務(wù)。 為簡單起見,讓我們假設(shè)以下用例。
開發(fā)服務(wù)
可以通過兩種方式完成:“代碼優(yōu)先”和“合同優(yōu)先”。 我們將使用代碼優(yōu)先方法。
創(chuàng)建服務(wù)端點(diǎn)接口(SEI)
讓我們創(chuàng)建一個名為BookShelfService的SEI接口
package com.aranin.weblog4j.services;import com.aranin.weblog4j.vo.BookVO;import javax.jws.WebMethod; import javax.jws.WebService;@WebService public interface BookShelfService {@WebMethodpublic String insertBook(BookVO bookVO);@WebMethodpublic BookVO getBook(String title); }如果看上面的SEI,可以看出它是一個普通的Java接口,但有兩個注釋
- @WebService –這是一個注釋JAXWS庫。 它將普通的POJO轉(zhuǎn)換為Web服務(wù)。 在我們的例子中,注釋位于接口定義的正上方,它通知BookShelfService不是普通接口,而是Web服務(wù)接口或SEI。 該注釋還有其他一些屬性可以完全定義Web服務(wù),但是我們現(xiàn)在不會使用它。
- @WebMethod –此注釋是可選的,主要用于為wsdl中的公共方法提供名稱屬性。
實施服務(wù)。
現(xiàn)在我們有了SEI,因此讓我們在BookShelfServiceImpl的接口中實現(xiàn)方法
package com.aranin.weblog4j.services;import com.aranin.weblog4j.hashdb.HashDB; import com.aranin.weblog4j.vo.BookVO;import javax.jws.WebService;@WebService(endpointInterface = "com.aranin.weblog4j.services.BookShelfService",serviceName="bookShelfService") public class BookShelfServiceImpl implements BookShelfService {public String insertBook(BookVO bookVO) {HashDB.insertBook(bookVO);return "Book with name : " + bookVO.getBookName() + " is now available on the shelf"; //To change body of implemented methods use File | Settings | File Templates.}public BookVO getBook(String title) {return HashDB.getBook(title); //To change body of implemented methods use File | Settings | File Templates.} }此類是實現(xiàn)SEI的簡單POJO。 這里唯一值得注意的是@WebService批注。 如果您仔細(xì)看一下,我們提供了它實現(xiàn)的SEI的完全合格的類名和Web服務(wù)的名稱。
數(shù)據(jù)綁定類(BookVO)
package com.aranin.weblog4j.vo;import javax.xml.bind.annotation.XmlRootElement; import java.io.Serializable;@XmlRootElement(name = "Book") public class BookVO implements Serializable {private long bookId;private String bookName;private String author;public long getBookId() {return bookId;}public void setBookId(long bucketId) {this.bookId = bookId;}public String getBookName() {return bookName;}public void setBookName(String bookName) {this.bookName = bookName;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;} }這里唯一要注意的是@XmlRootElement批注。 該注釋是JAXB庫的一部分。 CXF使用JAXB作為默認(rèn)數(shù)據(jù)綁定組件。 由于BookVO在Web服務(wù)調(diào)用期間需要作為XML進(jìn)行傳輸,因此需要在CXF安裝中由JAXB引擎進(jìn)行編組/解組。 使用@XmlRootElement批注,我們可以幫助JAXB將BookVO類映射到xml,并將其name屬性作為xml的根元素。
基于Spring的服務(wù)器Bean
使CXF成為Web服務(wù)框架的第一選擇的原因在于,它通過基于Spring的配置文件發(fā)布其服務(wù)端點(diǎn)。 讓我們創(chuàng)建一個配置文件并在其中注冊我們的服務(wù)。 我們將文件命名為beans.xml并將其保存在應(yīng)用程序的WEB-INF文件夾中
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:jaxws="http://cxf.apache.org/jaxws"xmlns:jaxrs="http://cxf.apache.org/jaxrs"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://cxf.apache.org/jaxrshttp://cxf.apache.org/schemas/jaxrs.xsdhttp://cxf.apache.org/jaxwshttp://cxf.apache.org/schemas/jaxws.xsd"><import resource="classpath:META-INF/cxf/cxf.xml" /> <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" /> <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> <jaxws:endpointid="bookShelfService"implementor="com.aranin.weblog4j.services.BookShelfServiceImpl"address="/bookshelfservice" /></beans>現(xiàn)在要加載beans.xml,我們只需在web.xml中添加以下內(nèi)容
<context-param> <param-name>contextConfigLocation</param-name><param-value>/WEB-INF/beans.xml,/WEB-INF/applicationContext.xml</param-value> </context-param>最后,我們需要通過web.xml連接spring和CXF。
<servlet><servlet-name>CXFServlet</servlet-name><display-name>CXF Servlet</display-name><servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class><load-on-startup>2</load-on-startup> </servlet><servlet-mapping><servlet-name>CXFServlet</servlet-name><url-pattern>/*</url-pattern> </servlet-mapping>注意:我沒有包括Spring ContextLoaderListner的加載。 如果您使用struts2入門原型通過maven創(chuàng)建了struts2應(yīng)用程序,那么spring將由maven項目本身下載并注冊。
現(xiàn)在您的Web服務(wù)已準(zhǔn)備就緒。 在任何servlet容器中編譯和部署應(yīng)用程序。 如果一切都很好,那么您可以在以下位置看到您的wsld: http:// localhost:8080 / weblog4jdemo / bookshelfservice?wsdl
創(chuàng)建您的客戶
有許多工具可用于使用wsdl生成客戶端代碼。 為了節(jié)省您的更多麻煩,我們將利用CXF自己的前端api。 因此,讓我們看看步驟。
這是上述調(diào)用的輸出
INFO: Creating Service {http://services.weblog4j.aranin.com/}BookShelfServiceService from class com.aranin.weblog4j.services.BookShelfService result : Book with name : Foundation and Earth is now available on the shelf result : Book with name : Foundation and Empire is now available on the shelf result : Book with name : Rama Revealed is now available on the shelf book name : Foundation and Earth book author : Issac AsimovProcess finished with exit code 0您可以在Apache CXF中探索大量其他內(nèi)容,例如創(chuàng)建動態(tài)客戶端,攔截器,利用其他傳輸協(xié)議,基于https的Web服務(wù)等。但是,我打算將本文作為入門教程。
ew,這又是一個漫長的帖子。 我需要提高寫作技巧以縮短篇幅。 但我仍然希望您喜歡它并發(fā)現(xiàn)它有用。 我打算在我的下一篇文章中撰寫有關(guān)Web服務(wù)的javascript客戶端的文章。 在那之前,再見,編碼愉快。
翻譯自: https://www.javacodegeeks.com/2013/06/developing-soap-web-service-using-apache-cxf.html
總結(jié)
以上是生活随笔為你收集整理的使用Apache CXF开发SOAP Web服务的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 天赋是什么意思(天赋异禀是什么意思)
- 下一篇: 使用Apache Lucene 4.3轻