技巧: 用 JAXM 发送和接收 SOAP 消息—Java API 使许多手工生成和发送消息方面必需的步骤自动化...
簡介:?在本篇技巧文章中,作者兼開發人員 Nicholas Chase 向您演示如何使用用于 XML 消息傳遞的 Java API(Java API for XML Messaging (JAXM))簡化創建和發送 SOAP 消息的過程。
Web 服務的基礎在于以標準格式發送和接收消息以便使所有系統都能理解。通常,那種格式是簡單對象訪問協議(Simple Object Access Protocol (SOAP))。SOAP 消息可以手工生成和發送,但是用于 XML 消息傳遞的 Java API(JAXM)使許多必需步驟(如創建連接或創建并發送實際消息)自動化。這篇技巧文章記錄了一個同步 SOAP 消息的創建和發送。
這個過程包含五個步驟:
JAXM 可以作為 Java XML Pack(2002 年春季版)的一部分和 Java Web Services Developer Pack EA2(請參閱?參考資料)的一部分而獲得。后者還包含了一份 Tomcat Web 服務器以及樣本應用程序的副本。那些樣本 Web 服務之一作為本技巧文章中 SOAP 消息的目的地,這個例子中實際服務的內容和功能卻不是很重要。
SOAP 消息結構
一個基本的 SOAP 消息由包含兩個主要部分(報頭和主體)的封套組成。應用程序決定如何使用這些部分,但整個消息必須遵循特定的 XML 結構,例如:
樣本 SOAP 消息
| <soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"><soap-env:Header/><soap-env:Body><cal:schedule xmlns:cal="http://www.example.com/calendar"><cal:newitem><cal:eventDate>4/10/2002</cal:eventDate><cal:title>Fun With Frogs</cal:title></cal:newitem></cal:schedule></soap-env:Body> </soap-env:Envelope> |
?
在這個例子中,報頭為空,而主體包含目的地為一個日歷應用程序的信息。
請注意這個消息的結構。Envelope 包含 Header 和 Body 元素,而三者全都是?http://schemas.xmlsoap.org/soap/envelope/?名稱空間的一部分。整個消息將通過一個 SOAP 連接發送到一個 Web 服務中。
回頁首
創建連接和消息
第一步是創建整個類和連接:
創建連接
| import javax.xml.soap.SOAPConnectionFactory; import javax.xml.soap.SOAPConnection; public class SOAPTip {public static void main(String args[]) {try {//First create the connectionSOAPConnectionFactory soapConnFactory = SOAPConnectionFactory.newInstance();SOAPConnection connection = soapConnFactory.createConnection();//Close the connection connection.close();} catch(Exception e) {System.out.println(e.getMessage());}} } |
?
SOAP 消息可以通過使用?SOAPConnection?直接發送,或使用消息傳遞提供程序間接發送。在這個例子中,應用程序通過使用工廠(factory)創建?SOAPConnection?對象。
工廠也創建消息本身:
創建消息對象
| import javax.xml.soap.SOAPConnectionFactory; import javax.xml.soap.SOAPConnection; import javax.xml.soap.MessageFactory; import javax.xml.soap.SOAPMessage; import javax.xml.soap.SOAPPart; import javax.xml.soap.SOAPEnvelope; import javax.xml.soap.SOAPBody; public class SOAPTip {public static void main(String args[]) {try {//First create the connectionSOAPConnectionFactory soapConnFactory = SOAPConnectionFactory.newInstance();SOAPConnection connection = soapConnFactory.createConnection();//Next, create the actual messageMessageFactory messageFactory = MessageFactory.newInstance();SOAPMessage message = messageFactory.createMessage();//Create objects for the message parts SOAPPart soapPart = message.getSOAPPart();SOAPEnvelope envelope = soapPart.getEnvelope();SOAPBody body = envelope.getBody();//Close the connection connection.close();} catch(Exception e) {System.out.println(e.getMessage());}} } |
?
首先,通過使用?MessageFactory?來創建消息本身。這個消息已包含如?envelope?和?header?等基本部分的空白版本。?SOAPPart?包含envelope?,而?envelope?包含主體。同時創建所需對象(如?SOAPBody?)的引用。
接著,填充?SOAPBody?:
填充主體
| ... import javax.xml.soap.SOAPBody; import javax.xml.soap.SOAPElement; public class SOAPTip {public static void main(String args[]) {try { ...//Create objects for the message parts SOAPPart soapPart = message.getSOAPPart();SOAPEnvelope envelope = soapPart.getEnvelope();SOAPBody body = envelope.getBody();//Populate the body//Create the main element and namespaceSOAPElement bodyElement = body.addChildElement(envelope.createName("schedule" , "cal", "http://www.example.com/calendar"));//Add contentbodyElement.addChildElement("cal:newitem").addTextNode("contentHere");//Save the messagemessage.saveChanges();//Check the inputSystem.out.println("\nREQUEST:\n");message.writeTo(System.out);System.out.println();//Close the connection connection.close();} catch(Exception e) {System.out.println(e.getMessage());}} } |
?
SOAP 消息的主體就象任何其它 XML 元素,您可以在其中添加子元素(如?schedule?元素)。通常,您可以使用?addChildElement(elementname)?,但是這里演示的?envelope.createName()?方法使用用于數據或有效負載的名稱空間聲明簡化了元素的創建。的確,創建 schedule 元素從而創建了?bodyElement SOAPElement?對象。然后,?bodyElement?對象可以給其自己的子元素?cal:newitem?添加其自己的文本節點。通過這種方式,您可以象構建任何其它 XML 文檔一樣構建 XML 結構。
然而,使用 JAXM,您也有機會通過使用外部文件直接創建消息的?SOAPPart?。例如,第一個清單中的 XML 結構保存在文件prepped.msg?中,而且可以調用它來替代手工構建文檔。
從外部文件創建消息
| ... import javax.xml.soap.SOAPElement; import java.io.FileInputStream; import javax.xml.transform.stream.StreamSource; public class SOAPTip {public static void main(String args[]) { ...//Create objects for the message parts SOAPPart soapPart = message.getSOAPPart();SOAPEnvelope envelope = soapPart.getEnvelope();SOAPBody body = envelope.getBody();//Populate the MessageStreamSource preppedMsgSrc = new StreamSource( new FileInputStream("prepped.msg"));soapPart.setContent(preppedMsgSrc);//Save the messagemessage.saveChanges(); ...} } |
?
結果就是準備發送的 SOAP 消息。
回頁首
發送消息
對于同步消息,發送 SOAP 消息和接收應答是在單個步驟中發生的:
發送消息
| ... import javax.xml.messaging.URLEndpoint; public class SOAPTip {public static void main(String args[]) {...//Check the inputSystem.out.println("\nREQUEST:\n");message.writeTo(System.out);System.out.println();//Send the message and get a reply //Set the destinationURLEndpoint destination = new URLEndpoint("http://localhost:8080/jaxm-simple/receiver");//Send the messageSOAPMessage reply = connection.call(message, destination);//Close the connection connection.close(); ...} } |
?
實際的消息是使用?call()?方法發送的,該方法把消息本身和目的地作為參數,然后返回第二個?SOAPMessage?作為應答。目的地必須是一個?Endpoint?對象,或者是這個例子中的?URLEndpoint?。這個示例使用來自 JWSDP 的一個樣本 servlet,它只用于獲取響應。
call()?方法一直處于阻塞狀態,直到它接收到返回的?SOAPMessage?為止。
回頁首
響應
返回的?SOAPMessage?―?reply?― 是 SOAP 消息,它與已發送的消息格式相同,因此可以象操作任何其它 XML 消息那樣操作它。SOAP 允許您通過使用 XSLT 直接轉換應答:
讀取響應
| ... import javax.xml.transform.TransformerFactory; import javax.xml.transform.Transformer; import javax.xml.transform.Source; import javax.xml.transform.stream.StreamResult; public class SOAPTip {public static void main(String args[]) {try {...//Send the messageSOAPMessage reply = connection.call(message, destination);//Check the outputSystem.out.println("\nRESPONSE:\n");//Create the transformerTransformerFactory transformerFactory = TransformerFactory.newInstance();Transformer transformer = transformerFactory.newTransformer();//Extract the content of the replySource sourceContent = reply.getSOAPPart().getContent();//Set the output for the transformationStreamResult result = new StreamResult(System.out);transformer.transform(sourceContent, result);System.out.println();//Close the connection connection.close(); ... } } |
?
象在任何 XSLT 應用程序中那樣創建?Transformer?對象。在這個例子中,我們只希望輸出內容,所以沒有用到樣式表。這里,內容本身就是消息的整個 SOAP 部分(與可能包含附件的 SOAP 消息本身不同)。您還可以在處理之前抽取封套和主體。這個例子中的結果只是?System.out?,但它可以是通常用于轉換的任何選擇。照常進行轉換。
圖 1. SOAP 請求和響應?
?
回頁首
下一步
雖然本示例中的端點是提供靜態響應的 servlet,但是實際的響應取決于服務的功能和請求的性質。同時,雖然本篇技巧文章演示了消息的同步發送和接收,但是通過使用?ProviderConnection?對象而不是?SOAPConnection?,JAXM 允許使用消息傳遞提供程序進行異步發送。該提供程序一直保存這個消息,直到成功發送消息為止。
JAXM 還允許使用?profile,這樣很容易創建諸如 SOAP-RP 或 ebXML 消息那樣的專門 SOAP 消息,而且還能使非 XML 附件能夠附加到 SOAP 消息中。
參考資料
- 您可以參閱本文在 developerWorks 全球站點上的?英文原文.?
- 請查看?W3C中的各種與 Web 服務相關的建議書的情況。?
- JAXM 可以作為?Java XML Pack(2002 年春季版)的一部分和?Java Web Services Developer Pack EA2的一部分而獲得。?
- IBM WebSphere Studio Application Developer是用于構建、測試和部署 Web 服務的易用的集成開發環境。?
- 要獲取完整的 Web 服務工具箱,請下載 IBM 的?Web Services Development Kit。?
- 在 developerWorks 的?XML和?Web 服務專區查找更多參考資料。
- 您可以參閱本文在 developerWorks 全球站點上的?英文原文.?
轉載:http://www.ibm.com/developerworks/cn/xml/tips/x-jaxmsoap/
轉載于:https://www.cnblogs.com/chenying99/archive/2013/05/23/3094128.html
總結
以上是生活随笔為你收集整理的技巧: 用 JAXM 发送和接收 SOAP 消息—Java API 使许多手工生成和发送消息方面必需的步骤自动化...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 笔记1-3: 从标准输入读取命令并执行
- 下一篇: 选房心得