`
schy_hqh
  • 浏览: 555877 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

深入SOAP发送消息的过程(SAAJ)

 
阅读更多

SOAP结构体
SOAPMessage
    SOAPPart
        SOAPEnvelope
            SOAPHeader(optional)
            SOAPBody(XML Content or SOAPFault)
    AttachmentPart
        MIME Headers
        Content(XML or non-XML)


服务端
IMyService.java
package com.hqh.soap;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;


@WebService
public interface IMyService {
	
	@WebResult(name="addResult")
	public int add(@WebParam(name="a")int a,@WebParam(name="b")int b);
	
}	


MyServiceImpl.java
package com.hqh.soap;

import javax.jws.WebService;

@WebService(endpointInterface="com.hqh.soap.IMyService")
public class MyServiceImpl implements IMyService {

	@Override
	public int add(int a, int b) {
		System.out.println("MyServiceImpl.add()");
		return a+b;
	}

}



开启/运行服务
MyServer.java
package com.hqh.soap;

import javax.xml.ws.Endpoint;

public class MyServer {
	public static void main(String[] args) {
		String address = "http://localhost:8888/ms";
		IMyService implementor = new MyServiceImpl();
		Endpoint.publish(address, implementor);
	}
}



向服务端发送SOAP消息
TestSOAP.java
package com.hqh.soap;

import java.io.IOException;
import java.net.URL;

import javax.xml.namespace.QName;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service;

import org.junit.Test;
import org.w3c.dom.Document;

public class TestSOAP {
	/**
	 * 演示SOAP消息的创建过程
	 */
	@Test
	public void test01() {
		//1.创建消息工厂
		try {
			MessageFactory factory = MessageFactory.newInstance();
			
			//2.使用factory创建SoapMessage
			SOAPMessage message = factory.createMessage();
			
			//创建soapPart
			SOAPPart part = message.getSOAPPart();
			
			//获取soapEnvelope信封
			SOAPEnvelope envelope = part.getEnvelope();
			
			//通过信封就可以获取head和body的相关信息
			SOAPBody body = envelope.getBody();
			
			//根据QName创建相应节点【QName就是一个带有命名空间的节点】
			String namespaceURI = "http://webservice/example/soap";
			String localPart = "add";
			String prefix = "ns";
			QName qName = new QName(namespaceURI, localPart, prefix);
			//<ns:add xmlns="http://webservice/example/soap"/>
			
			SOAPBodyElement bodyEle = body.addBodyElement(qName);
			bodyEle.addChildElement("a").setValue("1");
			bodyEle.addChildElement("b").setValue("9");
			
			//body.addBodyElement(qName).setValue("<a>1</a> <b>2</b>");
			
			
			//打印消息
			message.writeTo(System.out);
			
			
		} catch (SOAPException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	
	
	/**
	 * 模拟SOAP发送消息,接收返回值的过程
	 */
	@Test
	public void test02() {
		try {
			//1.创建服务
			URL wsdlDocumentLocation = new URL("http://localhost:8888/ms?wsdl");
			String ns = "http://soap.hqh.com/";//wsdl的命名空间
			String localPart = "MyServiceImplService";//服务的名称
			QName serviceName = new QName(ns,localPart);
			Service service = Service.create(wsdlDocumentLocation, serviceName);
			
			//2.创建Dispatch
			QName portName = new QName(ns,"MyServiceImplPort");
			Dispatch<SOAPMessage> dispatch = 
					service.createDispatch(portName, SOAPMessage.class, Service.Mode.MESSAGE);
			
			//3.创建SOAPMessage
			SOAPMessage message = MessageFactory.newInstance().createMessage();
			SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
			SOAPBody body = envelope.getBody();
			
			//4.通过QName指定消息中需要传递的数据
			String prefix = "nn";//前缀必须指定,任意
			String invokeMethodName = "add";//指定服务端被调用的方法
			QName ename = new QName(ns, invokeMethodName, prefix);
			
			SOAPBodyElement bodyElement = body.addBodyElement(ename);
			bodyElement.addChildElement("a").setValue("12");
			bodyElement.addChildElement("b").setValue("32");
			
			message.writeTo(System.out);
			System.out.println("invoking...");
			//5.传递消息
			SOAPMessage retMessage = dispatch.invoke(message);
			retMessage.writeTo(System.out);
			System.out.println();
			
			//将相应的消息转换为dom对象
			Document doc = retMessage.getSOAPPart().getEnvelope().getBody().extractContentAsDocument();
			String retValue = doc.getElementsByTagName("addResult").item(0).getTextContent();
			System.out.println("retValue="+retValue);
			
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			
		}
	}
}



运行结果
发送的数据:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
	<SOAP-ENV:Header />
	<SOAP-ENV:Body>
		<nn:add xmlns:nn="http://soap.hqh.com/">
			<a>12</a>
			<b>32</b>
		</nn:add>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

接收的数据:
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
	<S:Header />
	<S:Body>
		<ns2:addResponse xmlns:ns2="http://soap.hqh.com/">
			<addResult>44</addResult>
		</ns2:addResponse>
	</S:Body>
</S:Envelope>



package com.hqh.soap;
import java.util.List;

import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;


@WebService
public interface IMyService {
	
	@WebResult(name="addResult")
	public int add(@WebParam(name="a")int a,@WebParam(name="b")int b);
	
	@WebResult(name="user")
	public User addUser(@WebParam(name="user")User user);
	
	@WebResult(name="user")
	public User login(@WebParam(name="username")String username,@WebParam(name="pwd")String pwd);
	
	@WebResult(name="user")
	public List<User> list();
	
}	




package com.hqh.soap;

import java.util.ArrayList;
import java.util.List;

import javax.jws.WebService;

@WebService(endpointInterface="com.hqh.soap.IMyService")
public class MyServiceImpl implements IMyService {

	private static List<User> users = new ArrayList<User>();
	
	public MyServiceImpl() {
		users.add(new User(1,"admin","admin"));
	}
	
	@Override
	public int add(int a, int b) {
		System.out.println("MyServiceImpl.add()");
		return a+b;
	}

	@Override
	public User addUser(User user) {
		users.add(user);
		return user;
	}

	@Override
	public User login(String username, String pwd) {
		for(User user:users) {
			if(username.equals(user.getName()) && pwd.equals(user.getPwd()))
				return user;
		}
		return null;
	}

	@Override
	public List<User> list() {
		return users;
	}

}



使用payload传递user对象

1.创建对象并使用JAXB将其转换为xml格式
2.组装part节点
3.将part节点转换为Source源
4.通过dispatcher发送数据并接收返回的Source
5.将返回的Source转换为DomResult
6.通过DomResult获取Node
7.通过xpath从node获取NodeList
8.再通过JAXB的unmarshaller将node转换为User对象

/**
	 * 模拟SOAP发送消息,接收返回值的过程
	 * 使用payload方式传输,不是以message的方式传递,而是以字符串的形式完成数据传输
	 */
	@Test
	public void test03() {
		try {
			//1.创建服务
			URL wsdlDocumentLocation = new URL("http://localhost:8888/ms?wsdl");
			String ns = "http://soap.hqh.com/";//wsdl的命名空间
			String localPart = "MyServiceImplService";//服务的名称
			QName serviceName = new QName(ns,localPart);
			Service service = Service.create(wsdlDocumentLocation, serviceName);
			
			//2.创建Dispatch
			QName portName = new QName(ns,"MyServiceImplPort");
			//通过元数据的方式传递
			Dispatch<Source> dispatch = 
					service.createDispatch(portName, Source.class, Service.Mode.PAYLOAD);
			
			//3.使用JAXB将对象转换为xml
			User jaxbElement = new User(100,"root","root");
			JAXBContext ctx = JAXBContext.newInstance(User.class);
			Marshaller marshaller = ctx.createMarshaller();
			//不要生成xml头:<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
			marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
			Writer writer = new StringWriter();
			//将转换后的xml写入到字符输出流中
			marshaller.marshal(jaxbElement, writer);
			System.out.println(writer);
			//转换后的结果:<user><id>100</id><name>root</name><pwd>root</pwd></user>
			
			//4.封装Part
			String payload = "<nn:addUser xmlns:nn=\""+ns+"\">"+writer+"</nn:addUser>";
			System.out.println(payload);
			//<nn:addUser xmlns:nn="http://soap.hqh.com/"><user><id>100</id><name>root</name><pwd>root</pwd></user></nn:addUser>
			
			//5.通过dispatcher传递source
			//将字符串转换为Source类型
			Source reqSource = new StreamSource(new StringReader(payload));
			//发送数据并得到返回的Source
			Source respSource = dispatch.invoke(reqSource);
			
			//6.转换返回的Source为DomSource
			DOMResult domResult = new DOMResult(); 
			Transformer trans = TransformerFactory.newInstance().newTransformer();
			trans.transform(respSource, domResult);
			
			//7.处理转换后的DomResult获取结果
			Node node = domResult.getNode();
			XPath xpath = XPathFactory.newInstance().newXPath();
			NodeList nodeList = (NodeList) xpath.evaluate("//user", node, XPathConstants.NODESET);
			//反编排,将Node转换为对象
			User user = (User)ctx.createUnmarshaller().unmarshal(nodeList.item(0));
			System.out.println(user);
			//结果:User [id=100, name=root, pwd=root]
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			
		}
	}


通过Message传递List
	/**
	 * 通过Message传递List
	 */
	@Test
	public void test04() {
		try {
			//1.创建服务
			URL wsdlDocumentLocation = new URL("http://localhost:8888/ms?wsdl");
			String ns = "http://soap.hqh.com/";//wsdl的命名空间
			String localPart = "MyServiceImplService";//服务的名称
			QName serviceName = new QName(ns,localPart);
			Service service = Service.create(wsdlDocumentLocation, serviceName);
			
			//2.创建Dispatch
			QName portName = new QName(ns,"MyServiceImplPort");
			Dispatch<SOAPMessage> dispatch = 
					service.createDispatch(portName, SOAPMessage.class, Service.Mode.MESSAGE);
			
			//3.创建SOAPMessage
			SOAPMessage message = MessageFactory.newInstance().createMessage();
			SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
			SOAPBody body = envelope.getBody();
			
			//4.通过QName指定消息中需要传递的数据
			String prefix = "nn";//前缀必须指定,任意
//			String invokeMethodName = "add";//指定服务端被调用的方法
			String invokeMethodName = "list";//指定服务端被调用的方法
			QName ename = new QName(ns, invokeMethodName, prefix);
			
			SOAPBodyElement bodyElement = body.addBodyElement(ename);
//			bodyElement.addChildElement("a").setValue("12");
//			bodyElement.addChildElement("b").setValue("32");
			
			message.writeTo(System.out);
			System.out.println("\n invoking...");
			//5.传递消息
			SOAPMessage retMessage = dispatch.invoke(message);
			retMessage.writeTo(System.out);
			System.out.println();
			
			//将相应的消息转换为dom对象
			Document doc = retMessage.getSOAPPart().getEnvelope().getBody().extractContentAsDocument();
//			String retValue = doc.getElementsByTagName("addResult").item(0).getTextContent();
//			System.out.println("retValue="+retValue);
			
			//通过dom获取node;通过node转换为对象
			JAXBContext ctx = JAXBContext.newInstance(User.class);
			List<User> userList = new ArrayList<User>();
			NodeList nodeList = doc.getElementsByTagName("user");
			for(int i=0;i<nodeList.getLength();i++) {
				Node node = nodeList.item(i);
				User u = (User)ctx.createUnmarshaller().unmarshal(node);
				userList.add(u);
			}
			for(User u : userList) {
				System.out.println(u);
			}
			
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			
		}
	}


结果:

list中user对象的个数与执行test03相关(addUser)。
User [id=1, name=admin, pwd=admin]
User [id=100, name=root, pwd=root]
User [id=100, name=root, pwd=root]
分享到:
评论

相关推荐

    使用SAAJ 和JAXM的 SOAP客户端及服务

    SAAJ(SOAP with Attachments API for Java)和JAXM(Java API for XML Messaging)是Java平台上的两个重要工具,它们分别用于处理SOAP消息和XML消息的发送与接收。本文将深入探讨如何利用SAAJ和JAXM来构建SOAP...

    saaj soap动态调用

    通过`SOAPConnectionFactory`的`createConnection()`方法获取`SOAPConnection`,然后调用其`call()`方法发送SOAP消息。 2. **SOAPPart和SOAPEnvelope**:`SOAPMessage`对象包含一个`SOAPPart`,它是整个SOAP消息的...

    Java SOAP协议

    此示例展示了如何使用SAAJ创建SOAP消息的各个部分,并通过SOAP连接将其发送到指定URL。 ### 结论 SAAJ和JAXM是处理SOAP消息的重要工具,在Java Web服务开发中具有重要作用。通过对这些API的理解和掌握,开发者能够...

    SOAP入门

    6. **获取消息内容**:最后,如果接收到一个SOAP响应,可以使用类似的过程来解析和访问消息的内容。 #### 三、向Header添加内容 除了Body部分,SOAP消息还允许在Header中添加内容。Header可以包含元数据,如认证...

    用Java实现基于SOAP的XML文档网络传输及远程过程调用(RPC).

    本文将深入探讨如何使用Java来实现基于SOAP的XML文档网络传输以及远程过程调用(RPC)。这是一项关键的技术,它允许不同系统间的无缝交互,即使这些系统采用不同的编程语言和平台。 SOAP是一种基于XML的协议,主要...

    Soap Tutorial

    本文档将引导您从创建和发送简单消息开始,逐步深入到SOAP的高级功能。 二、创建并发送简单消息 在开始使用SOAP之前,首先需要了解如何创建一个SOAP消息。SAAJ(SOAP with Attachments API for Java)提供了创建...

    xmldsig.jar,saaj-api-1.3.jar,activation.jar相关jar包资源

    `saaj-api`定义了与SOAP消息处理相关的API,包括解析、创建、修改和发送SOAP消息。开发人员可以使用这个API来实现客户端和服务端的SOAP通信。`saaj-api-1.3.jar`对应的是版本1.3,其中包含了对SOAP 1.1和1.2的支持。...

    soap入门(E版)soap入门(E版)

    - **SAAJ(SOAP with Attachments API for Java)** 提供了对SOAP消息的API支持,包括创建、修改和发送带有附件的消息。 - **DOM(Document Object Model)** 是一种处理XML文档的标准API,可用于构建和修改SOAP...

    soap开发所有包(最全)

    例如,通过SAAJ库,开发者可以方便地创建和发送SOAP消息;使用JAX-WS,可以从WSDL自动生成服务端和客户端的Java代码。 总之,这个“soap开发所有包”集合对于初学者和有经验的开发者来说都是一份宝贵的资源,它涵盖...

    soap模拟客户端和服务端(tomca的 soap 服务t配置省略)

    在本主题中,我们将深入探讨如何模拟SOAP客户端和服务端,尤其是在Tomcat服务器环境中。 首先,理解SOAP的基本结构至关重要。一个SOAP消息通常包括三部分:Header、Body和Envelope。Header部分包含消息处理信息,如...

    JAVA的WebService支持CXF与SAAJ第三版

    - **JAXM**:Java API for XML Messaging,主要用于发送和接收基于SOAP的消息。 - **SAAJ**:SOAP with Attachments API for Java,提供了构建和解析SOAP消息的能力,特别支持附件传输。 - **特点**: - 更多地暴露...

    技巧:用JAX-RPC发送与接收SOAP消息

    虽然发送SOAP消息有多种方式,但基本方法通常涉及直接向URL流执行`println`操作,这种方式不仅要求开发者具备深入的SOAP协议知识,还需要了解特定服务预期的SOAP消息格式。由于这些信息难以直接从服务中获取,所以该...

    开发所需用的到资源包

    JAXM提供了一种编程模型,用于发送和接收基于SOAP的消息。虽然在Java SE 6之后被JAX-WS取代,但在某些老版本或者特定场景下,JAXM仍然是处理SOAP消息的重要工具。 这个压缩包中的“saaj与jaxm开发所需jar包”很可能...

    sping 提供的 webservice

    首先,定义一个消息处理器,该处理器会将输入参数转化为 SOAP 消息,然后通过 `WebServiceTemplate` 发送请求。接收到响应后,再将 SOAP 消息转化为结果对象。 **6. 示例代码** 在提供的压缩包 `spring-axis-1` 中...

    Bubbles:Java SOAP 客户端

    在这个"Bubbles: Java SOAP 客户端"项目中,我们将深入探讨如何在Java环境中创建一个能够发送和接收SOAP消息的客户端。 首先,我们需要理解SOAP消息的基本结构。SOAP消息通常包含三个主要部分:Header、Body和...

    jax-ws 2.0文档说明以及源码

    在JAX-WS中,SAAJ用于构建和发送SOAP请求,处理SOAP响应。例如,`SOAPBody`、`SOAPEnvelope`和`SOAPHeader`都是SAAJ中的关键类。 **四、WSDL** WSDL是一种XML格式,用于描述Web服务的接口、操作、消息和绑定。JAX-...

    WebService的几种不同实现方式

    2. JAXM&SAAJ:JAXM(Java API for XML Messaging)主要定义了发送和接收SOAP消息的API,而SAAJ(SOAP With Attachments API for Java,JSR67)提供了构建和解析SOAP消息包的支持。这两个规范提供了更多SOAP协议底层...

    CXF使用手册

    JAXM定义了发送和接收消息所需的API,而SAAJ提供了SOAP包的构建与解析功能,特别支持附件传输。与JAX-WS相比,JAXM&SAAJ提供了更多底层细节的操作,但编码相对繁琐。 JAX-RS则是针对REST风格Web服务的规范,它的...

    WebService应用实例及教程

    - 客户端可以使用SOAP库(如Java的SAAJ或.NET的SoapHttpClient)创建SOAP消息并发送请求。 - 或者使用基于RESTful风格的调用方式,利用HTTP的GET、POST等方法。 5. WebService实例 - 假设我们有一个名为...

    axis入门中文文档

    2. 直接使用SOAP请求:如果对SOAP消息格式熟悉,也可直接构造SOAP请求,通过HTTP POST发送到服务地址。 六、SOAP详解 SOAP是一种轻量级的消息协议,用于在Internet上交换结构化的和类型化的信息。SOAP消息由三部分...

Global site tag (gtag.js) - Google Analytics