網絡服務
讓我們首先談談它本身的Web服務。 什么是Web服務。 人們傾向于說Web服務不僅僅是遠程方法調用(RMI)的過程。 實際上,這不僅僅與RMI有關。 Web服務是通過HTTP協議公開的端點(或單個端點)的集合。 為了與這些端點進行通信,我們必須創建客戶端以訪問端點。 Web服務端點和客戶端之間的這種通信的最大優點是由SOAP協議指定的,該協議建立在HTTP協議(有時甚至是SMTP協議)的基礎上。
該協議定義了在端點和客戶端之間傳輸的數據的結構。 數據以XML格式交換。 結果,Web服務被稱為獨立于“平臺/技術”。 例如,可以通過使用Java CXF框架或純JBoss Web服務來實現Web服務。 可以在非Java環境中實現訪問此Web服務的客戶端。 Web服務技術和客戶端技術可以完全不同,并且由于SOAP協議依賴于XML消息格式,因此它們之間仍可以進行通信。 要使通信成功,唯一需要做的事情就是端點和客戶端都同意XML消息的外觀(XML文件中將包含哪種字段和內容類型)以及進行哪些操作(方法),客戶端可以在端點上調用。
這些要求由WSDL指定。 WSDL (Web服務描述語言)是一種基于XML的語言,用于描述Web服務的端點。 它可以定義端點的HTTP地址,客戶端可以在此端點上執行的操作,可以傳遞給操作的數據類型以及從端點的那些操作返回的數據類型。 它還定義了與端點進行通信時使用的XML消息的確切結構。 這種信息通常以wsdl擴展名存儲在文件中。 這就是著名的術語“ wsdl文件”如何出現的原因。
好的,關于Web服務就足夠了。 實際上,我可以寫很多有關Web服務和SOAP協議的信息,但這超出了本博客的范圍。 鼓勵您這樣做。 互聯網上有很多關于該主題的文章。
在JBoss上創建一個簡單的Web服務
示例我將向您展示eclipse 3.7(indigo),我將使用JBoss 4.2.3.GA作為服務器。 作為項目構建工具,我將使用Maven。 讓我們從在Eclipse中創建最簡單的Web項目開始。 它將保存Web服務實現(端點)。
它只是普通Web應用程序的Maven項目。 沒什么特別的。 如果您不想使用Maven,那也可以。 您可以使用自己喜歡的任何工具來創建簡單的Web應用程序。
在本文中,我將不介紹如何創建此簡單項目的詳細信息。 相反,我將為您提供日食中項目結構的屏幕快照。
|
日食中的項目結構。 |
現在,讓我們創建Web服務。 我們將采用“ 自下而上的方法 ”。 這意味著我們將首先開發一個實現類,然后再定義WSDL。 因此,讓我們編寫一個簡單的java POJO類。 我們只是假裝我們的Web服務將某種汽車ID作為參數并返回該汽車的價格。 如果我們輸入不存在的汽車ID,則Web服務將返回相應的錯誤文本。
這里要注意的主要元素是CarWebService接口和CarWebServiceImpl類,它們實際上實現了端點接口。
讓我們從CarWebService接口開始。 這是代碼:
package ba.codecentric.webservice;import javax.jws.WebMethod;
import javax.jws.WebService;import ba.codecentric.webservice.model.CarResponse;@WebService
public interface CarWebService {@WebMethodpublic CarResponse getCarPrice(String carId);}
如您所見,這是一個普通的接口定義。 這里只有兩件事需要注意:兩個注釋: @WebService和@WebMethod 。 這些注釋屬于稱為JAX-WS的技術領域。 JAX-WS是有關如何創建Web服務和客戶端的規范,它們可以與RPC調用進行通信并交換基于XML的消息。 Java具有自己的JAX-WS實現,使我們能夠使用這些簡單的注釋來定義Web服務端點。 您可以在此處閱讀有關JAX-WS的更多信息。 在Java內部,該技術處理接收和解析XML消息(通常與SOAP協議交換)。 這使開發人員免去了許多小時的辛苦工作,因此開發人員不必花費時間編寫代碼來生成肥皂消息,發送它,然后在服務器端接收它,從xml中提取信息等。所有這些就是由Java中的JAX-WS機制在內部完成。
因此,當您希望在服務器上創建純Java Web服務端點時,只需創建接口即可。 用WebService批注標記接口,并將接口中希望公開的所有方法標記為遠程方法(帶有WebMethod批注)。 然后,這些將成為可以在接口上調用的操作。 在我的示例中,我只有一種方法,但是可以有更多種方法。
下一站是創建接口實現。 我們已經公開了Web服務方法(端點的操作)。 這些方法必須執行某些操作才能使Web服務有意義。 在Java中,這非常簡單。 我們將只為接口創建實現類。
我將向您展示CarWebServiceImpl的代碼。
package ba.codecentric.webservice.impl;import java.util.HashMap;
import java.util.Map;import javax.jws.WebService;import ba.codecentric.webservice.CarWebService;
import ba.codecentric.webservice.model.CarResponse;@WebService(endpointInterface = 'ba.codecentric.webservice.CarWebService')
public class CarWebServiceImpl implements CarWebService {private final Map<String, Integer> prices = new HashMap<String, Integer>();public CarWebServiceImpl() {prices.put('audi', Integer.valueOf(10000));prices.put('bmw', Integer.valueOf(15000));prices.put('fiat', Integer.valueOf(5000));}public CarResponse getCarPrice(String carId) {Integer price = prices.get(carId);CarResponse response = new CarResponse();if(price == null) {response.setCarPrice(-1);response.setStatus('error: no car with id: ' + carId);} else {response.setCarPrice(price.intValue());response.setStatus('ok');}return response;}}
再次需要注意的是特殊注釋。 與界面相同,但只有一個額外的參數。 它是端點接口的標準名稱。 沒有其他的。
在現實世界中,此Web服務可能具有更復雜的代碼。 它將需要某種汽車ID,然后將在數據庫中搜索汽車。 但是在這里,我變得更加簡單。 我有一張地圖,其中包含三種不同的汽車ID,其中存儲了ID的價格。
如果將現有的汽車ID傳遞給服務(例如audi,bmw),則將從服務器上的Web服務獲得響應。 響應將包含狀態消息(確定)和汽車價格。
如果您將不存在的汽車ID傳遞給服務,則您將收到狀態錯誤的響應,并且還會有一個詳細的字符串,告訴您未找到要搜索的汽車。 在這種情況下,汽車價格將設置為-1。
好。 就Web服務實現而言就是這樣。 很簡單,不是嗎? 僅要做一件事。 而且這一過程更加簡單。 您需要將實現類公開為Servlet。 您將在web.xml中執行此操作。 這是代碼:
<servlet><servlet-name>carWebservice</servlet-name><servlet-class>ba.codecentric.webservice.impl.CarWebServiceImpl</servlet-class></servlet><servlet-mapping><servlet-name>carWebservice</servlet-name><url-pattern>/ws/car</url-pattern></servlet-mapping>
我們完成了。 現在,我們需要打包應用程序并將其部署到JBoss。
JBoss將為您發布此端點,因此您無需擔心。
所以請繼續。 將您的應用程序部署到JBoss。 如果您將maven用作構建工具,則pom.xml應該如下所示:
<build><finalname>webservices</finalName><plugins><plugin><groupid>org.apache.maven.plugins</groupId><artifactid>maven-compiler-plugin</artifactId><version>2.5.1</version><configuration><source>1.6</source><target>1.6</target></configuration></plugin></plugins>
</build>
由于使用了注釋,因此將Maven編譯器的源版本和目標版本設置為Java 6。
JBoss擁有自己的小型Web應用程序,可讓您查看當前部署的所有Web服務以及這些Web服務的所有WSDL文件的位置。
您可以從以下URL訪問此小型應用程序: http:// localhost:8080 / jbossws / services
當然,只要您的JBoss服務器名稱為localhost且其http端口配置為8080。
這是我的PC上的屏幕截圖,清楚地表明了在此示例中部署的Web服務確實正在運行。
您可以單擊端點的URL。 結果將是您實際上將看到端點的WSDL。 在該WSDL中,您將看到類似<import location ='……'>的內容 。 location屬性的值是完整WSDL的真實URL。 所以請繼續。 同時在瀏覽器中打開該URL。 現在,您應該看到整個WSDL(端點定義,可以調用的操作,發送到端點并從端點接收回的消息)。 我希望這可以使您更輕松地了解Web服務實際上是如何與客戶端交換數據的。 客戶端只是基于從Web服務獲取的WSDL文件創建請求。 在該WSDL文件中,客戶端可以看到與端點進行通信所需的所有內容。 SOAP協議和Java的JAX-WS機制負責其余所有工作。 開發人員不必查看其中已調用的操作。
創建一個簡單的Web服務客戶端(wsconsume實用程序)
為了調用此Web服務,我們需要創建一個客戶端。 客戶端可以是一個簡單的Java控制臺應用程序。 如果您不想使事情復雜化,它甚至不必是Web應用程序。 這意味著您可以使用main()方法創建一個簡單的Java類。 只需幾行代碼,您就完成了。 我們在這里要做的第一件事是生成所謂的“存根類”。 這些類表示我們用于與Web服務通信的模型請求和響應類。 如果您還記得的話,我已經創建了一個特殊的包裝器類來返回Web服務響應。 但是,這些存根類中不只是模型類。 在這里,您還將找到實際執行遠程端點調用的類以及其他一些實用程序類。 另外,您還會發現將Java對象編組和解編為XML消息時所需的一些JAXB注釋,反之亦然。 這些存根類是基于端點的WSDL文件創建的。 如果您還記得WSDL文件,則包含客戶端需要的所有信息。 基于WSDL文件,我們可以生成所有必需的存根類(用于與Web服務通信的模型類和用于促進此通信的實用程序類)。 對我們來說幸運的是,JBoss有一個小的實用程序,我們將使用它來生成這些類。 對于這些存根類,我們不必編寫任何代碼。 我們還可以告訴該工具立即在工作空間中生成類。 真的很酷的東西。 因此,讓我們試一試。 該工具稱為wsconsume.bat ,位于JBoss文件夾– bin中。 對于Linux用戶,有wsconsume.sh 。
首先,我將在Eclipse中為此生成一個不同的項目。 我將其稱為ws-client 。 這是一個普通的Java項目。 您可以選擇File-> New-> Java Project并使用所有默認設置。 好。 現在,我們準備創建存根類。 我們希望wsconsume實用程序將類立即放入Java源文件的src文件夾中。 并且我們還將告訴wsconsume實用程序應該用于這些類的軟件包的確切名稱。 我的項目位于此處: D:\ JBossTests \ jbossWebServiceWorkspace \ ws-client 。
因此,wsconsume utlity的命令應為:D:\ JBossTests \ jboss-4.2.3.GA \ bin> wsconsume -v -k -p ws.client.impl -s D:\ JBossTests \ jbossWebServiceWorkspace \ ws-client \ src
http://127.0.0.1:8080/webservices/ws/car?wsdl
確保您正在jboss bin文件夾中執行此命令。 否則,請確保您的路徑上具有wsconsume.bat文件,以從任何文件夾訪問該文件。
還要確保您的jboss正在運行,并且您要為其嘗試生成客戶端的Web服務已正確部署并正在運行。
讓我們解釋一下我在這里使用的參數:
-v:詳細(如果有錯誤,則顯示完整的錯誤堆棧跟蹤);
-k:保留/生成Java源代碼;
-p:軟件包名稱。 生成的類將立即獲得給定的包; -s:源文件夾。 放置源文件的目錄。 我在客戶端項目中使用了源文件夾,這很有意義。
最后,我們有了端點的WSDL位置的URL。
您可以打開jboss URL http:// localhost:8080 / jbossws / services來查看當前已部署的所有Web服務以及所有WSDL URL。 您只需將所需的WSDL URL復制/粘貼到wsconsume實用程序的命令提示符下即可。 在我們的例子中,這是我們先前創建的Web服務的位置。
現在轉到eclipse并刷新新客戶端項目中的src文件夾。 現在,您應該具有由wsconsume實用程序生成的某些類,并且這些類應位于指定的程序包中。 現在我們需要做的就是執行此客戶端并將請求發送到Web服務。 只需再創建一個類即可。 我將其稱為CarWebserviceClient 。 我將其放入單獨的包裝中。 此類將具有普通的java main方法。 軟件包為ws.client.runner :
package ws.client.runner;import ws.client.impl.CarResponse;
import ws.client.impl.CarWebService;
import ws.client.impl.CarWebServiceImplService;public class CarrWebserviceClient {public static void main(String[] args) {CarWebServiceImplService service = new CarWebServiceImplService();CarWebService port = service.getCarWebServiceImplPort();CarResponse audiPrice = port.getCarPrice('audi');System.out.println('audi price: ' + audiPrice.getCarPrice() + ' EUR; web service status: ' + audiPrice.getStatus());CarResponse fordPrice = port.getCarPrice('ford');System.out.println('ford price: ' + fordPrice.getCarPrice() + ' EUR; web service status: ' + fordPrice.getStatus());}}
如您所見,上面的代碼非常簡單。 您只需要實例化客戶端,然后獲取服務的端口即可。 我們可以通過調用具有相同名稱的java方法來調用Web服務操作。 只需傳遞您想要的參數即可。 您可以將audi , bmw和fiat用作硬編碼的現有值。 您也可以嘗試檢索一些不存在的汽車ID的價格。 我在上面的示例中嘗試過。
當然,不要忘了運行jboss并部署Web服務,以使其工作:-)
好吧,僅此而已。 這可能是繼續進入基于SOAP的Web服務世界的一個不錯的起點。 這是最基本的示例,通過使用JAX-WS API并在jboss支持Web服務的幫助下實現。
參考:來自JCG合作伙伴 Branislav Vidovi的JBoss上的Core Java Web Services ? 在極客的東西:-)博客上。
翻譯自: https://www.javacodegeeks.com/2012/08/jboss-core-java-web-services.html