转自:https://www.cnblogs.com/chenying99/archive/2013/05/23/3094128.html

简介: 在本篇技巧文章中,作者兼开发人员 Nicholas Chase 向您演示如何使用用于 XML 消息传递的 Java API(Java API for XML Messaging (JAXM))简化创建和发送 SOAP 消息的过程。

Web 服务的基础在于以标准格式发送和接收消息以便使所有系统都能理解。通常,那种格式是简单对象访问协议(Simple Object Access Protocol (SOAP))。SOAP 消息可以手工生成和发送,但是用于 XML 消息传递的 Java API(JAXM)使许多必需步骤(如创建连接或创建并发送实际消息)自动化。这篇技巧文章记录了一个同步 SOAP 消息的创建和发送。

这个过程包含五个步骤:

  1. 创建 SOAP 连接
  2. 创建 SOAP 消息
  3. 填充消息
  4. 发送消息
  5. 检索应答

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 connection
SOAPConnectionFactory 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 connection
SOAPConnectionFactory soapConnFactory =
SOAPConnectionFactory.newInstance();
SOAPConnection connection =
soapConnFactory.createConnection(); //Next, create the actual message
MessageFactory 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 namespace
SOAPElement bodyElement =
body.addChildElement(envelope.createName("schedule" ,
"cal",
"http://www.example.com/calendar"));
//Add content
bodyElement.addChildElement("cal:newitem").addTextNode("contentHere");
//Save the message
message.saveChanges();
//Check the input
System.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 Message
StreamSource preppedMsgSrc = new StreamSource(
new FileInputStream("prepped.msg"));
soapPart.setContent(preppedMsgSrc);
//Save the message
message.saveChanges();
...
}
}

结果就是准备发送的 SOAP 消息。

 

回页首

发送消息

对于同步消息,发送 SOAP 消息和接收应答是在单个步骤中发生的:

发送消息

...
import javax.xml.messaging.URLEndpoint;
public class SOAPTip { public static void main(String args[]) { ...
//Check the input
System.out.println("\nREQUEST:\n");
message.writeTo(System.out);
System.out.println();
//Send the message and get a reply //Set the destination
URLEndpoint destination =
new URLEndpoint("http://localhost:8080/jaxm-simple/receiver");
//Send the message
SOAPMessage 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 message
SOAPMessage reply = connection.call(message, destination);
//Check the output
System.out.println("\nRESPONSE:\n");
//Create the transformer
TransformerFactory transformerFactory =
TransformerFactory.newInstance();
Transformer transformer =
transformerFactory.newTransformer();
//Extract the content of the reply
Source sourceContent = reply.getSOAPPart().getContent();
//Set the output for the transformation
StreamResult 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 消息中。

参考资料

转载:http://www.ibm.com/developerworks/cn/xml/tips/x-jaxmsoap/

2.技巧: 用 JAXM 发送和接收 SOAP 消息—Java API 使许多手工生成和发送消息方面必需的步骤自动化的更多相关文章

  1. (七)发送、接收SOAP消息(以HttpClient方式)(2)

    一.为什么要用soap 原本我们使用web服务都是根据wsdl生成客户端(生成一堆java文件)然后再调用,本章节讲解如何用soap消息来替代这种方式. 二.SOAP消息格式 SOAP(简单对象访问协 ...

  2. (六)发送、接收SOAP消息(1)

    一.为什么要用soap 原本我们使用web服务都是根据wsdl生成客户端(生成一堆java文件)然后再调用,本章节讲解如何用soap消息来替代这种方式. 二.SOAP消息格式 SOAP(简单对象访问协 ...

  3. 传说中的WCF(4):发送和接收SOAP头

    如果你实在不明白Header是个啥玩意儿,你就想一想你发送电子邮件时,是不是有个叫“附件”的东东?对啊,那么SOAP头是不是可以理解为一种附加信息?就是附加到消息正文的内容. 消息正文又是啥?WCF除 ...

  4. 重温WCF之发送和接收SOAP头(三)

    SOAP头可以理解为一种附加信息,就是附加到消息正文的内容. 既然消息头是附加信息,那有啥用呢?你可别说,有时候还真有不少用处.举个例子,WCF的身份验证是不是很麻烦?还要颁发什么证书的(当然不是荣誉 ...

  5. 安装比特币区块链钱包API(Blockchain Wallet用户发送和接收比特币的简单API)

    区块链钱包API提供了一个简单的界面,商家可以用它以编程方式与钱包进行交互. 安装:要使用此API,您需要运行负责管理区块链钱包的小型本地服务. 您的应用程序通过HTTP API调用在本地与此服务进行 ...

  6. Android深入四大组件(八)广播的注册、发送和接收过程

    前言 我们接着来学习Android四大组件中的BroadcastReceiver,广播主要就是分为注册.接收和发送过程.建议阅读此文前请先阅读Android深入理解四大组件系列的文章,知识重复的部分, ...

  7. 转-Web Service中三种发送接受协议SOAP、http get、http post

    原文链接:web服务中三种发送接受协议SOAP/HTTP GET/HTTP POST 一.web服务中三种发送接受协议SOAP/HTTP GET/HTTP POST 在web服务中,有三种可供选择的发 ...

  8. android 蓝牙编程重点---如何发送和接收16进制数据

    最近的android蓝牙开发项目也逐渐接近尾声,基本的功能都已经完成,只剩下界面的设计.现在真的是舒了一口气! 作为编程学习经验只有1年的菜鸟,这是我独自完成的商业性产品,而且还是涉及到与单片机蓝牙模 ...

  9. Android中实现APP文本内容的分享发送与接收方法简述

    谨记(指定选择器Intent.createChooser()) 开始今天的内容前,先闲聊一下: (1)突然有一天头脑风暴,对很多问题有了新的看法和见解,迫不及待的想要分享给大家,文档已经写好了,我需要 ...

随机推荐

  1. Python 调用snmp自定义OID实现监控

    http://kkkkkk.blog.51cto.com/468162/1172726 http://blog.csdn.net/mirahs/article/details/49619729

  2. ArcGIS 空间查询

    public static bool QueryMessPoint(IActiveView activeView, IFeatureClass featureClass, string whereCl ...

  3. Maven的SSH搭建以及部署

    本人有点傻,研究Maven研究了有一段时间,刚刚有些入门,记录下来方便以后使用 工作环境:jdk7 myeclipse10 maven3.1.1 1 下载maven3.1.1 http://maven ...

  4. Python使用Redis实现一个简单作业调度系统

    Python使用Redis实现一个简单作业调度系统 概述 Redis作为内存数据库的一个典型代表,已经在非常多应用场景中被使用,这里仅就Redis的pub/sub功能来说说如何通过此功能来实现一个简单 ...

  5. D3.js 整体展示篇

    近期一段时间研究社会成员网络关系图的一些可视化展示,对大数据可视化这片荒漠一筹莫展的自己,幸好发现了D3这片充满活力的绿洲.我决定在这块宝地贪婪地大餐一番. 本文介绍主要来自官网翻译及用户使用后感想资 ...

  6. 在kettle中实现数据验证和检查

    在kettle中实现数据验证和检查 在ETL项目,输入数据通常不能保证一致性.在kettle中有一些步骤能够实现数据验证或检查.验证步骤能够在一些计算的基础上验证行货字段:过滤步骤实现数据过滤:jav ...

  7. Cocos2d-x学习笔记(十四)CCAutoreleasePool具体解释

    原创文章,转载请注明出处:http://blog.csdn.net/sfh366958228/article/details/38964637 前言 之前学了那么多的内容.差点儿全部的控件都要涉及内存 ...

  8. 【Linux】JDK+Eclipse 搭建C/C++开发环境

    注:本文所提供的参考示例是在CentOS Linux环境下的安装,不保证适用于其他版本的Linux系统. ·    安装前的注意事项 编译源代码是需要对应的代码编译工具的,本文中安装的Eclipse只 ...

  9. centos7 nginx搭建及其反向代理

    摘要:nginx反向代理的原理:外部通过ip加端口访问nginx,nginx接收到外部请求,通过ip解析访问内部服务器,内部服务器再将数据传回Nginx服务器,而Nginx再把数据传回给外部客户机. ...

  10. css3 实现动画效果

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...