接下来是关于在java中,SOAP的一些相关类和概念。
看之前需要理解SOAP的基本概念。
我们可以想到,在java 程序中发送一个SOAP request,不管是用什么方法,最终发送出去的一定就是一个标准的SOAP request。
只不过java包含一些类,代表了实际的SOAP request中不同部分。以及一些方法,帮助你构造SOAP request中的内容。
首先我们来看看,在java中是如何发送SOAP message的。
- 第一个类: SOAPConnection
final SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
final SOAPConnection soapConnection = soapConnectionFactory.createConnection();
SOAPMessage reply = soapConnection.call(loginSOAPRequest, new URL("http://172.28.85.6/ASAPService/ASAPService_V1.svc"));
因此发送SOAP request很简单,只需要构造一个SOAPConnection对象,然后运行call方法。
其中,被发送的loginSOAPRequest是之前构造出来的一个SOAPMessage对象,发送的目的URL就是web service的地址。
由代码可见,web services返回的response也是一个SOAPMessage对象。因此我们可以认定:
在java中,发送和接受的对象都是SOAPMessage。
我们可以进一步认定: SOAPMessage这个对象一定包含了SOAP以及http头的信息。只有这样发送出去的才是一个完整有效的SOAP request。
- 第二个类:SOAPMessage
首先明确一个概念:虽然SOAPMessage这个对象包含了http头的信息。但是java中并没有单独的类对应http头信息。
因为,http header的信息不需要代码自己构造,而是由java自动完成的。也就是说,在上文中看到的必须的http信息 POST, content_type等信息,都是自动填充的。
我们可以修改这些信息,后面将提到,但是不需要自己构造。
SOAPMessage对象包含两个部分:SOAPPart 和 AttachmentPart. 其中SOAPPart 是必须有的部分,AttachmentPart是可选的部分。
SOAPPart 其实就是完整的SOAP request。它包含http头和SOAP message信息。SOAPPart必须是XML结构的。
AttachmentPart可以有零个或多个,可以理解为,它是SOAP中可以携带的附加信息,例如图片,音频等信息。
SOAPPart 和 AttachmentPart都由下面两个部分组成:
application-specific content and associated MIME headers.
MIME ( Multipurpose Internet Mail Extension) 的概念,在javax.xml.soap有对应的类。只要是这个类的子类就可以使用SOAP传输。
其中MIME headers代表的就是下面的这部分http头信息:
POST /item HTTP/1.1
Host: 189.123.345.239
Content-Type: text/plain
Content-Length: 200
SOAPAction: "http://ASAP.services.tfn.**.com/2010-03-01/Login"
但正如前面所说,我们并不需要直接构造这么一个string。SOAPMessage在实例化时会自动构造出默认的MIMEHeader,我们可以修改它:
MimeHeaders hd = loginSOAPRequest.getMimeHeaders(); //loginSOAPRequest是之前构造好的一个SOAPMessage。
hd.setHeader("SOAPAction", "http://ASAP.services.tfn.**.com/2010-03-01/Login";);
//这句将MIMEHeader中包含的SOAPAction部分由默认的“”,修改为指定的样子。
The one new piece here is that SOAP 1.1 requires the client to set a SOAPAction field in the HTTP header.
AttachmentPart可以是非XML结构的。关于AttachmentPart,本文不准备多说。
SOAPMessage类中有很多方法可以用于操作这些包含的对象。
可以使用MessageFactory来创建一个SOAPMessage。然后再向这个message中添加需要的信息。
SOAPMessage可以用来:
- create a point-to-point connection to a specified endpoint
- create a SOAP message
- create an XML fragment
- add content to the header of a SOAP message
- add content to the body of a SOAP message
- create attachment parts and add content to them
- access/add/modify parts of a SOAP message
- create/add/modify SOAP fault information
- extract content from a SOAP message
- send a SOAP request-response message
- SOAPPart
看过了SOAPMessage,我们知道SOAPPart其实是SOAP消息的主体。
SOAPMessage包含SOAPPart 对象,SOAPPart 包含了SOAPEnvelope 对象,而SOAPEnvelope 又包含了SOAPBody 和SOAPHeader 对象。如下:
SOAPEnvelope se = sp.getEnvelope();
SOAPBody sb = se.getBody();
SOAPHeader sh = se.getHeader();
正如java API中描述的:SOAPPart object, which contains information used for message routing and identification, and which can contain application-specific content.
上面这些类的层次关系和SOAP协议中的语法结构是一致的。
我们可以方便的创建一个SOAPMessage。此时会有一个默认的SOAPPart属于这个SOAPMessage。
之后我们可以用SOAPPart的方法方便的往SOAPPart中添加信息:
setContent(); //Sets the content of the SOAPEnvelope
object with the data from the givenSource
object.
联想一下前面各个对象的关系我们就可以知道,这个方法实际set了SOAPEnvelop, SOAPBody. SOAPFault, SOAPHeader。
- SOAPElement
An object representing an element of a SOAP message that is allowed but not specifically prescribed by a SOAP specification. This interface serves as the base interface for those objects that are specifically prescribed by a SOAP specification.
即element可以代表在SOAPMessag中任何一个element,不管这个element是SOAPBody还是SOAPEnvelope。
- SOAPFactory
SOAPFactory
is a factory for creating various objects that exist in the SOAP XML tree.SOAPFactory
can be used to create XML fragments that will eventually end up in the SOAP part.
因此SOAPFactory可以用来读取XML tree,并创建对应的SOAPElement。之后可以方便的将SOAPElement加到SOAPMessage中去。
-
Transformer
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer();
transformer.transform(new DOMSource(doc), new DOMResult(parent));//将XML对象doc转换成DOM对象
return (SOAPElement) parent.getChildElements().next();//取得所有的childElement并返回
通过使用Transformer对象和SOAPElement对象,我们就可以方便的实现读入一个XML,转换成SOAPElement,之后构造成SOAPMessage,最终发送给web service。
也可以将DOM对象转换成XML对象,然后打印输出。
下面是一个极其简单的使用SOAP的示例,从文件读入一个SOAP message并发送给web service:
//Send SOAP request messages and then return response.
public SOAPMessage sendSOAPMessage() throws Exception {
//用工厂创建一个SOAPMessage
MessageFactory mf = MessageFactory.newInstance() ;
SOAPMessage loginSOAPRequest = mf.createMessage();
//给这个SOAPMessge添加信息,来源就是d:\\testSOAP.txt文件,内容是标准的SOAP
SOAPPart sp = loginSOAPRequest.getSOAPPart();
StreamSource prepMsg = new StreamSource(
new FileInputStream("d:\\testSOAP.txt"));
sp.setContent(prepMsg);
final String SOAPACTION = "http://ASAP.services.tfn.thomson.com/2010-03-01/Login";
//将SOAPAction添加到MimeHeaders中去
MimeHeaders hd = loginSOAPRequest.getMimeHeaders();
hd.setHeader("SOAPAction", SOAPACTION);
//将上面的更改保存
loginSOAPRequest.saveChanges();
//创建一个SOAPConnection。具体方法在前面的SOAPConnection中已经说了
SOAPConnection con = getSoapConnection();
//发送SOAP request 。这里目标地址可以是web services或tornado。
SOAPMessage reply = con.call(loginSOAPRequest, new URL("http://172.28.85.6/ASAPService/ASAPService_V1.svc"));
con.close();
//返回response
return reply;
}
下面这个方法接收一个SOAPMessage,并将其内容打印到文件中。据此我们可以检查构造的SOAPMessage是否是自己希望的内容。
private void getSoapContent(SOAPMessage loginSOAPRequest) {
String output = "d:\\test1.txt";
try{
FileOutputStream tt = new FileOutputStream(output);
loginSOAPRequest.writeTo(tt);
tt.toString();
}catch(Exception e){
System.out.println();
}
}
一个需要知道的名词:
SAAJ refer to SOAP with Attachments API for JavaTM (SAAJ)
其他可以参考的代码示例是:
http://technet.rapaport.com/Info/Prices/SampleCode/Java_Webservice_Example.aspx