JAX-WS – Soap详解[通俗易懂]

JAX-WS – Soap详解[通俗易懂]一、创建Soap //创建消息工厂 MessageFactoryfactory=MessageFactory.newInstance(); //通过工厂创建Soap的消息 SOAPMessagemessage=factory.createMessage(); //获取SoapPart SOAPPartpart=message.getSO

大家好,又见面了,我是你们的朋友全栈君。

一、创建Soap

    代码示例如下:

	@Test
	public void createSoap() throws Exception{
		
		// 创建消息工厂
		MessageFactory factory = MessageFactory.newInstance();
		
		// 通过工厂创建Soap的消息
		SOAPMessage message = factory.createMessage();
		
		// 获取SoapPart
		SOAPPart part = message.getSOAPPart();
		
		// 获取Soap信封Envelope
		SOAPEnvelope envelope = part.getEnvelope();
		
		// 通过Soap信封获取body和header的信息
		SOAPBody body = envelope.getBody();
		
		// 根据QName创建相应的节点(QName就是一个带有命名空间的节点:<ns:add xmls="http://www.xilen.com/webservice"/> )
		QName qname = new QName("http://webservice.xilen.com", "add", "ns");
		
		//通过soapBody传入QName添加body元素
		SOAPBodyElement bodyElement = body.addBodyElement(qname);
		
		// 对body添加子元素 (或者直接对body元素设置值:bodyElement.setValue("5"); )
		SOAPElement childElement = bodyElement.addChildElement("a");
		
		// 对body子元素设置值
		childElement.setValue("7");
		
		// 继续添加第二个子元素 (或者继续对子元素添加子元素:childElement.addChildElement("acn").setValue("acv");)
		bodyElement.addChildElement("b").setValue("5");
		
		// 打印最终得到的Soap消息
		message.writeTo(System.out);
		
	}

    得到的Soap消息如下:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
	<SOAP-ENV:Header/>
	<SOAP-ENV:Body>
		<ns:add xmlns:ns="http://webservice.xilen.com">
			<a>7</a>
			<b>5</b>
		</ns:add>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

二、发送Soap消息

    1、基于MESSAGE的方式

        代码示例如下:

	@Test
	public void sendSoapByMessage() throws Exception{
		
		/**
		 *  定义相关变量(wsdl文档的路径、接口的命名空间、实现的命名空间)
		 */
		String wsdlUrl = "http://localhost:8888/user?wsdl";
		String implNS = "http://impl.soap.xilen.com/";
		String inteNS = "http://soap.xilen.com/";
		
		
		/**
		 *  创建服务
		 */
		URL url = new URL(wsdlUrl);
		// 通过wsdl实现部分的命名空间创建服务的QNane,因为Service的描述在实现部分的命名空间中(详见 六、附录 中的截图)
		QName serviceQname = new QName(implNS, "UserServiceImplService");
		Service service = Service.create(url, serviceQname);
		
		
		/**
		 *  创建Dispatch (通过SOAPMessage传递) 
		 */
		Dispatch<SOAPMessage> dispatch =
				// portName:wsdl文件中Service节点中的prot的name属性值的QName; type:消息类型; mode:消息传递的类型(message|payLoad)
				service.createDispatch(new QName(implNS, "UserServiceImplPort"), SOAPMessage.class, Service.Mode.MESSAGE);
		
		
		/**
		 *  创建SoapMessage
		 */
		SOAPMessage message = MessageFactory.newInstance().createMessage();
		SOAPEnvelope envelope =  message.getSOAPPart().getEnvelope();
		SOAPBody body = envelope.getBody();
		// 通过wsdl接口部分的命名空间创建消息的QNane,因为Message的描述在接口部分的命名空间中<span style="font-family: Arial, Helvetica, sans-serif;">(详见 六、附录 中的截图)</span>
		QName soapQname = new QName(inteNS, "login", "ns");
		SOAPBodyElement bodyElement = body.addBodyElement(soapQname);
		bodyElement.addChildElement("name").setValue("admin");
		bodyElement.addChildElement("pass").setValue("12345");
		
		
		/**
		 *  输出即将发送的Soap消息
		 */
		message.writeTo(System.out);
		
		System.out.println("-------------------------- out 分隔线 in ----------------------------------");
		
		/**
		 * 通过dispatch传递消息
		 */
		SOAPMessage responseMessage = dispatch.invoke(message);
		
		
		/**
		 *  输出返回的Soap消息
		 */
		responseMessage.writeTo(System.out);
		
		/**
		 *  处理返回的Soap消息得到需要的信息
		 */
		String result = responseMessage.getSOAPBody().getElementsByTagName("loginResult").item(0).getTextContent();
		// 或者采用如下方式得到需要的信息
		    // String result = responseMessage.getSOAPPart().getEnvelope().getBody().extractContentAsDocument().
			//	  getElementsByTagName("addResult").item(0).getTextContent();
		
		/** 
		 * 输出通过返回Soap消息得到的信息
		 */
		System.out.println("return-->" + result);
		
	}

        Soap消息如下:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
	<SOAP-ENV:Header/>
	<SOAP-ENV:Body>
		<ns:login xmlns:ns="http://soap.xilen.com/">
			<name>admin</name>
			<pass>12345</pass>
		</ns:login>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

<!-------------------------- out 分隔线 in ---------------------------------->

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
	<S:Header/>
	<S:Body>
		<ns2:loginResponse xmlns:ns2="http://soap.xilen.com/">
			<loginResult>admin, welcome!</loginResult>
		</ns2:loginResponse>
	</S:Body>
</S:Envelope>

    2、基于PAYLOAD的方式

        代码示例如下:

@Test
	public void sendSoapByPayload() throws Exception{

		/**
		 *  定义相关变量(wsdl文档的路径、接口的命名空间、实现的命名空间)
		 */
		String wsdlUrl = "http://localhost:8888/user?wsdl";
		String implNS = "http://impl.soap.xilen.com/";
		String inteNS = "http://soap.xilen.com/";
		
		
		/**
		 * 创建服务
		 */
		URL url = new URL(wsdlUrl);
		// 通过wsdl实现部分的命名空间创建服务的QNane,因为Service的描述在实现部分的命名空间中
		QName serviceQname = new QName(implNS, "UserServiceImplService");
		Service service = Service.create(url, serviceQname);
		
		
		/**
		 * 创建Dispatch (通过Source传递)                    
		 */
		Dispatch<Source> dispatch =
				// portName:wsdl文件中Service节点中的prot的name属性值的QName; type:消息类型; mode:消息传递的类型(message|payLoad)
				service.createDispatch(new QName(implNS, "UserServiceImplPort"), Source.class, Service.Mode.PAYLOAD);
		
		
		/**
		 * 根据对象通过JAXB创建XML
		 */
		User user = new User(1L, "TestName", "TestPass");
		JAXBContext context = JAXBContext.newInstance(User.class);
		Marshaller marshaller = context.createMarshaller();
		// 取消xml的文档头和尾
		marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);  
		StringWriter writer = new StringWriter();
		marshaller.marshal(user, writer);
		
		/**
		 * 组建soap的xml
		 */
		String payload = "<ns:register xmlns:ns=\"" + inteNS + "\">" + writer.toString() + "</ns:register>";
		
		System.out.println(payload);
		
		
		/**
		 * 创建Source
		 */
		Source outSource = new StreamSource(new StringReader(payload));
		
		
		/**
		 * 通过dispatch传递负载(payLoad)
		 */
		Source inSource = dispatch.invoke(outSource);
		
		
		/**
		 * 将响应的Source转化为DOM进行操作获取需要的信息 (使用Transform对象转换)
		 */
		Transformer transformer = TransformerFactory.newInstance().newTransformer();
		DOMResult result = new DOMResult();
		transformer.transform(inSource, result);
		
		// 使用xpath查询
		XPath path = XPathFactory.newInstance().newXPath();
		NodeList nl = (NodeList) path.evaluate("//registerResult", result.getNode(), XPathConstants.NODESET);
		
		// 打印需要被获取的信息
		System.out.println(nl.item(0).getTextContent());
		
	}

        组建的Soap内容如下:

<ns:register xmlns:ns="http://soap.xilen.com/">
	<user>
		<id>1</id>
		<name>TestName</name>
		<pass>TestPass</pass>
	</user>
</ns:register>

三、列表响应处理

	@Test
	public void returnList() throws Exception{

		/**
		 *  定义相关变量(wsdl文档的路径、接口的命名空间、实现的命名空间)
		 */
		String wsdlUrl = "http://localhost:8888/user?wsdl";
		String implNS = "http://impl.soap.xilen.com/";
		String inteNS = "http://soap.xilen.com/";
		

		/**
		 *  创建服务
		 */
		URL url = new URL(wsdlUrl);
		// 通过wsdl实现部分的命名空间创建服务的QNane,因为Service的描述在实现部分的命名空间中
		QName serviceQname = new QName(implNS, "UserServiceImplService");
		Service service = Service.create(url, serviceQname);
		
		
		/**
		 *  创建Dispatch 
		 */
		Dispatch<SOAPMessage> dispatch =
				//      portName:wsdl文件中Service节点中的prot的name属性值的QName   type:消息类型         mode:消息传递的类型(message | payLoad)
				service.createDispatch(new QName(implNS, "UserServiceImplPort"), SOAPMessage.class, Service.Mode.MESSAGE);
		
		
		/**
		 * 创建SoapMessage
		 */
		SOAPMessage message = MessageFactory.newInstance().createMessage();
		SOAPEnvelope envelope =  message.getSOAPPart().getEnvelope();
		SOAPBody body = envelope.getBody();
		QName soapQname = new QName(inteNS, "list", "ns");
		SOAPBodyElement bodyElement = body.addBodyElement(soapQname);
		

		/**
		 * 通过dispatch传递消息
		 */
		SOAPMessage responseMessage = dispatch.invoke(message);
		
		// 转换body为document
		NodeList nodeList =  responseMessage.getSOAPPart().getEnvelope().getBody().
				extractContentAsDocument().getElementsByTagName("user"); 
		
		JAXBContext ctx = JAXBContext.newInstance(User.class);
		// Jaxb转换Node为User
		for (int i = 0; i < nodeList.getLength(); i++) {
			User u = (User) ctx.createUnmarshaller().unmarshal(nodeList.item(i));
			System.out.println(u);
		}
	}

四、显示配置Header

    示例代码如下:

	@Test
	public void sendSoapAddHeader() throws Exception{
		/**
		 *  定义相关变量(wsdl文档的路径、接口的命名空间、实现的命名空间)
		 */
		String wsdlUrl = "http://localhost:8888/user?wsdl";
		String implNS = "http://impl.soap.xilen.com/";
		String inteNS = "http://soap.xilen.com/";
		

		/**
		 *  创建服务
		 */
		URL url = new URL(wsdlUrl);
		QName serviceQname = new QName(implNS, "UserServiceImplService");
		Service service = Service.create(url, serviceQname);
		
		
		/**
		 *  创建Dispatch 
		 */
		Dispatch<SOAPMessage> dispatch =
				service.createDispatch(new QName(implNS, "UserServiceImplPort"), SOAPMessage.class, Service.Mode.MESSAGE);
		
		/**
		 * 创建SoapMessage
		 */
		SOAPMessage message = MessageFactory.newInstance().createMessage();
		SOAPEnvelope envelope =  message.getSOAPPart().getEnvelope();
		SOAPBody body = envelope.getBody();
		QName soapQname = new QName("http://soap.xilen.com/", "check", "ns");
		body.addBodyElement(soapQname);
		
		/**
		 * 添加Header
		 */
		SOAPHeader header = envelope.getHeader();
		// 判断是否有Header,没有则添加
		if(header == null){
			header = envelope.addHeader();
		}
		// 添加Header的内容
		QName headerQName = new QName("http://soap.xilen.com/", "name", "nn");
		SOAPHeaderElement headerElement = header.addHeaderElement(headerQName);
		headerElement.setValue("admin");
		header.addHeaderElement(new QName("http://soap.xilen.com/", "pass", "nn")).setValue("12345");
		
		
		message.writeTo(System.out);
		
		/**
		 * 通过dispatch传递消息
		 */
		SOAPMessage responseMessage = dispatch.invoke(message);

		
		/**
		 * 处理响应
		 */
		NodeList nodeList =  responseMessage.getSOAPPart().getEnvelope().getBody().
				extractContentAsDocument().getElementsByTagName("user");
		
		JAXBContext ctx = JAXBContext.newInstance(User.class);
		
		System.out.println("\n" + (User) ctx.createUnmarshaller().unmarshal(nodeList.item(0)));
	}

    发送的Soap如下:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
	<SOAP-ENV:Header>
		<nn:name xmlns:nn="http://soap.xilen.com/">admin</nn:name>
		<nn:pass xmlns:nn="http://soap.xilen.com/">12345</nn:pass>
	</SOAP-ENV:Header>
	<SOAP-ENV:Body>
		<ns:check xmlns:ns="http://soap.xilen.com/" />
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

五、服务端抛出异常

	@Test
	public void throwsException() throws Exception{
		/**
		 *  定义相关变量(wsdl文档的路径、接口的命名空间、实现的命名空间)
		 */
		String wsdlUrl = "http://localhost:8888/user?wsdl";
		String implNS = "http://impl.soap.xilen.com/";
		String inteNS = "http://soap.xilen.com/";
		

		/**
		 *  创建服务
		 */
		URL url = new URL(wsdlUrl);
		QName serviceQname = new QName(implNS, "UserServiceImplService");
		Service service = Service.create(url, serviceQname);
		
		
		/**
		 *  创建Dispatch 
		 */
		Dispatch<SOAPMessage> dispatch =
				service.createDispatch(new QName(implNS, "UserServiceImplPort"), SOAPMessage.class, Service.Mode.MESSAGE);
		
		/**
		 * 创建SoapMessage
		 */
		SOAPMessage message = MessageFactory.newInstance().createMessage();
		SOAPEnvelope envelope =  message.getSOAPPart().getEnvelope();
		SOAPBody body = envelope.getBody();
		QName soapQname = new QName(inteNS, "throwsException", "ns");
		body.addBodyElement(soapQname);

		
		/**
		 * try异常
		 */
		try {
			
			dispatch.invoke(message);
			
		} catch (Exception e) {
			
			System.out.println(e.getMessage());
		}
	}

六、附录

    1、WSDL概略图:

        JAX-WS - Soap详解[通俗易懂]

        JAX-WS - Soap详解[通俗易懂]

    2、服务端代码如下:

import java.util.List;

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

import com.xilen.entity.User;

@WebService
public interface UserService {

	/**
	 * 通过注解@WebParam对入参设置别名
	 * 通过注解@WebResult对出参设置别名
	 */
	@WebResult(name="loginResult")
	public String login(@WebParam(name="name") String name, @WebParam(name="pass") String pass);
	
	@WebResult(name="registerResult")
	public String register(@WebParam(name="user") User user);
	
	@WebResult(name="user")
	public List<User> list(); 
	
	/**
	 * 通过注解@WebParam的header属性设置入参为显示的Header
	 */
	@WebResult(name="user")
	public User check(@WebParam(name="name",header=true) String name, @WebParam(name="pass",header=true) String pass);
	
	public void throwsException() throws Exception;
	
}
import java.util.ArrayList;
import java.util.List;

import javax.jws.WebService;

import com.xilen.entity.User;
import com.xilen.soap.UserService;

@WebService(endpointInterface = "com.xilen.soap.UserService", serviceName = "UserServiceImplService")
public class UserServiceImpl implements UserService {

	@Override
	public String login(String name, String pass) {

		System.out.println("login info : [name=" + name + ", pass=" + pass
				+ "]");

		return name + ", welcome!";
	}

	@Override
	public String register(User user) {

		System.out.println(user);

		return user.getName() + ", registered!";
	}

	@Override
	public List<User> list() {

		List<User> list = new ArrayList<User>();
		list.add(new User(1L, "admin", "12345"));
		list.add(new User(2L, "super", "54321"));

		return list;

	}

	@Override
	public User check(String name, String pass) {

		System.out.println(name + "--->" + pass);

		return new User(1L, "admin", "12345");
	}

	@Override
	public void throwsException() throws Exception {

		throw new Exception("用户不存在!");
	}
}
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class User {
	private Long id;
	private String name;
	private String pass;
	
	public User() {
	}

	public User(Long id, String name, String pass) {
		super();
		this.id = id;
		this.name = name;
		this.pass = pass;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPass() {
		return pass;
	}

	public void setPass(String pass) {
		this.pass = pass;
	}

	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + ", pass=" + pass + "]";
	}
	
}
import javax.xml.ws.Endpoint;

import com.xilen.soap.impl.UserServiceImpl;

public class StartMain {
	
	public static void main(String[] args) {
		
		Endpoint.publish("http://localhost:8888/user", new UserServiceImpl());

	}

}

七、资源

    http://download.csdn.net/detail/u013379717/7453709 
 
 
 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/159697.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 【《重构 改善既有代码的设计》学习笔记6】重新组织函数

    本篇文章的内容来自《重构 改善既有代码的设计》一书学习笔记整理并且加上自己的浅显的思考总结!重构手法中,很大一部分是对函数进行整理,使之更恰当地包装代码。重新组织函数对过长的函数进行拆解,提炼函数,并处理局部变量,使得拆解后的函数更加清晰并且能够更好的工作。1、提炼函数(Extract Method)概要你有一段代码可以被组织在一起并独立起来。 将这段代码放进一个独立函数中,并让函…

  • java fgc_java Metaspace频繁FGC问题定位

    java fgc_java Metaspace频繁FGC问题定位问题描述数据服务是通过SQL对外提供数据查询的服务平台,底层存储支持HBase和MySQL两种。用户首先在管理平台上配置好接口的SQL详情SQL接口配置业务方通过微服务接口根据生成的ID以及接口参数来完成数据的查询,由于HBase不支持SQL引擎的查询,我们基于calcite实现了一套简单的SQLOnHBase解析逻辑。查看笔者前面的文章可以看到堆空间内存泄露的文章,可以了解相关的详情。但是不…

  • ITIL V3与ITIL V2的价值差异[通俗易懂]

    ITIL V3与ITIL V2的价值差异[通俗易懂]之前有篇日志写了ITILv3的介绍。这里说一下v3和v2才差异 ITILV3自从2007年推出后,已经将近两年了,这两年时间足够令相关的研究者和爱好者能知晓这个名词。对于新的名词、概念或者技术推出后,往往会有三个时期存在较多的争论,最热闹的时候一般是刚推出或临近推出的时期,而后慢慢冷淡一段时间后,不少有机会深入这些新事物的人慢慢地又会有第二个阶段的争论,最后一个阶段常常是这个新事物真正

  • 基于对话框的MFC程序实现RTL风格的一种方式[通俗易懂]

    基于对话框的MFC程序实现RTL风格的一种方式[通俗易懂]操作系统使用阿拉伯语时,微软操作系统为了适应阿拉伯语地区和希伯来语地区自右向左的阅读习惯,提供了独特的RTL的界面风格。怎么才能实现应用程序和操作系统保持一致的RTL风格呢?搜索了一些关于RTL界面实现的资料,网上大多数是通过遍历程序窗口,依次调用ModifyStyleEx系统API来实现的。基于对话框的MFC程序的窗口样式是通过资源文件预先定义的。基于对话框的…

  • 前端代码自动生成器「建议收藏」

    前端代码自动生成器「建议收藏」场景1.CodeFun是什么CodeFun是一款UI设计稿智能生成源代码的工具,支持微信小程序端、移动端H5和混合APP,上传Sketch、PSD等形式的设计稿,通过智能化技术一键生成可维护的前端代码.2.学习成本高吗?对于前端工程师来说,几乎没有学习成本。对于用惯了蓝湖/摹客的前端工程师来说,CodeFun使用流程与前者几乎一致:设计师上传完稿件后,工程师打开界面,选择任意需要的UI区域拷贝走想要的代码即可,只是从原来看标注变成了直接拷贝代码。对于设计师来说,完全不需要遵循某些设计规范

  • Windows系统通用定时关机命令

    Windows系统通用定时关机命令定时关机命令-s:表示关机-r:表示重启-t:表示时间(秒为单位)-a:表示取消关机10秒后关机shutdown-s-t10win10会弹出提示框提示关机时间,其它版本的系统右下角有提示,或者没有提示

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号