一、消息寻址
WS-Addressing是将消息路由数据包含在SOAP头中的一种标准方法。利用WS-Addressing的消息可以在标准化的SOAP头中包含自己的包含发送元数据,而不是依赖于网络层传输来传送路由信息。通过在标准的SOAP头中(wsa:ReplyTo)指定应答消息应该发送到哪里的端点引用,WS-Addressing可以支持异步交互方式。 服务提供者使用另一个连接,将应答消息发送给wsa:ReplyTo所指定的端点。这就将SOAP请求/应答消息的交互与HTTP请求/应答协议分离,这样,跨越任意时间的长时间运行的交互成为可能。
通过这种方式,当服务器端需要较长时间来处理业务的时候,不需要一直保持与客户端的连接,当处理完毕之后,服务器将结果返回给指定的客户端。这类似于异步的交互。
二、基于cxf的实现
编写wsdl文件,存放于工程的src目录下
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://apache.org/hello_world_soap_http"
xmlns:x1="http://apache.org/hello_world_soap_http/types" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="HelloWorld"
targetNamespace="http://apache.org/hello_world_soap_http">
<wsdl:types>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://apache.org/hello_world_soap_http/types"
elementFormDefault="qualified">
<element name="sayHi">
<complexType />
</element>
<element name="sayHiResponse">
<complexType>
<sequence>
<element name="responseType" type="xsd:string" />
</sequence>
</complexType>
</element>
<element name="greetMe">
<complexType>
<sequence>
<element name="requestType" type="xsd:string" />
</sequence>
</complexType>
</element>
<element name="greetMeResponse">
<complexType>
<sequence>
<element name="responseType" type="xsd:string" />
</sequence>
</complexType>
</element>
<element name="greetMeOneWay">
<complexType>
<sequence>
<element name="requestType" type="xsd:string" />
</sequence>
</complexType>
</element>
<element name="pingMe">
<complexType />
</element>
<element name="pingMeResponse">
<complexType />
</element>
<element name="faultDetail">
<complexType>
<sequence>
<element name="minor" type="xsd:short" />
<element name="major" type="xsd:short" />
</sequence>
</complexType>
</element>
</schema>
</wsdl:types>
<wsdl:message name="sayHiRequest">
<wsdl:part element="x1:sayHi" name="in" />
</wsdl:message>
<wsdl:message name="sayHiResponse">
<wsdl:part element="x1:sayHiResponse" name="out" />
</wsdl:message>
<wsdl:message name="greetMeRequest">
<wsdl:part element="x1:greetMe" name="in" />
</wsdl:message>
<wsdl:message name="greetMeResponse">
<wsdl:part element="x1:greetMeResponse" name="out" />
</wsdl:message>
<wsdl:message name="greetMeOneWayRequest">
<wsdl:part element="x1:greetMeOneWay" name="in" />
</wsdl:message>
<wsdl:message name="pingMeRequest">
<wsdl:part name="in" element="x1:pingMe" />
</wsdl:message>
<wsdl:message name="pingMeResponse">
<wsdl:part name="out" element="x1:pingMeResponse" />
</wsdl:message>
<wsdl:message name="pingMeFault">
<wsdl:part name="faultDetail" element="x1:faultDetail" />
</wsdl:message>
<wsdl:portType name="Greeter">
<wsdl:operation name="sayHi">
<wsdl:input message="tns:sayHiRequest" name="sayHiRequest" />
<wsdl:output message="tns:sayHiResponse" name="sayHiResponse" />
</wsdl:operation>
<wsdl:operation name="greetMe">
<wsdl:input message="tns:greetMeRequest" name="greetMeRequest" />
<wsdl:output message="tns:greetMeResponse" name="greetMeResponse" />
</wsdl:operation>
<wsdl:operation name="greetMeOneWay">
<wsdl:input message="tns:greetMeOneWayRequest" name="greetMeOneWayRequest" />
</wsdl:operation>
<wsdl:operation name="pingMe">
<wsdl:input name="pingMeRequest" message="tns:pingMeRequest" />
<wsdl:output name="pingMeResponse" message="tns:pingMeResponse" />
<wsdl:fault name="pingMeFault" message="tns:pingMeFault" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="Greeter_SOAPBinding" type="tns:Greeter">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="sayHi">
<soap:operation soapAction="" style="document" />
<wsdl:input name="sayHiRequest">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="sayHiResponse">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="greetMe">
<soap:operation soapAction="" style="document" />
<wsdl:input name="greetMeRequest">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="greetMeResponse">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="greetMeOneWay">
<soap:operation soapAction="" style="document" />
<wsdl:input name="greetMeOneWayRequest">
<soap:body use="literal" />
</wsdl:input>
</wsdl:operation>
<wsdl:operation name="pingMe">
<soap:operation style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
<wsdl:fault name="pingMeFault">
<soap:fault name="pingMeFault" use="literal" />
</wsdl:fault>
</wsdl:operation>
</wsdl:binding> <!-- SOAPService 的访问地址, 与server中的发布地址一致 -->
<wsdl:service name="SOAPService">
<wsdl:port binding="tns:Greeter_SOAPBinding" name="SoapPort">
<soap:address location="http://localhost:9000/SoapContext/SoapPort" />
<wswa:UsingAddressing xmlns:wswa="http://www.w3.org/2005/02/addressing/wsdl" />
</wsdl:port>
</wsdl:service> </wsdl:definitions>
服务实现类GreeterImpl:
package demo.ws_addressing.server; import java.util.logging.Logger; import javax.jws.WebService; import org.apache.hello_world_soap_http.Greeter;
import org.apache.hello_world_soap_http.PingMeFault;
import org.apache.hello_world_soap_http.types.FaultDetail; @WebService(name = "SoapPort", portName = "SoapPort", serviceName = "SOAPService", targetNamespace = "http://apache.org/hello_world_soap_http", wsdlLocation = "file:./src/hello_world_addr.wsdl")
// wsdlLocation 指定wsdl文件的地址
public class GreeterImpl implements Greeter { private static final Logger LOG = Logger.getLogger(GreeterImpl.class
.getPackage().getName()); public String greetMe(String me) {
LOG.info("Executing operation greetMe");
System.out.println("Executing operation greetMe");
System.out.println("Message received: " + me + "\n");
return "Hello " + me;
} public void greetMeOneWay(String me) {
LOG.info("Executing operation greetMeOneWay");
System.out.println("Executing operation greetMeOneWay\n");
System.out.println("Hello there " + me);
} public String sayHi() {
LOG.info("Executing operation sayHi");
System.out.println("Executing operation sayHi\n");
return "Bonjour";
} public void pingMe() throws PingMeFault {
FaultDetail faultDetail = new FaultDetail();
faultDetail.setMajor((short) 2);
faultDetail.setMinor((short) 1);
LOG.info("Executing operation pingMe, throwing PingMeFault exception");
System.out
.println("Executing operation pingMe, throwing PingMeFault exception\n");
throw new PingMeFault("PingMeFault raised by server", faultDetail);
} }
服务器端配置文件server.xml,存放在demo.ws_addressing.server包下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:cxf="http://cxf.apache.org/core" xmlns:wsa="http://cxf.apache.org/ws/addressing"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=" http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<cxf:bus>
<cxf:features>
<wsa:addressing />
</cxf:features>
</cxf:bus>
</beans>
服务端启动类Server:
package demo.ws_addressing.server; import java.net.URL;
import javax.xml.ws.Endpoint; import org.apache.cxf.Bus;
import org.apache.cxf.BusFactory;
import org.apache.cxf.bus.spring.SpringBusFactory; public class Server { protected Server() throws Exception {
System.out.println("Starting Server"); SpringBusFactory bf = new SpringBusFactory();
URL busFile = Server.class.getResource("server.xml");
Bus bus = bf.createBus(busFile.toString());
BusFactory.setDefaultBus(bus); Object implementor = new GreeterImpl();
String address = "http://localhost:9000/SoapContext/SoapPort"; // 发布服务地址,与wsdl中的访问地址一致
Endpoint.publish(address, implementor);
} public static void main(String args[]) throws Exception {
new Server();
System.out.println("Server ready..."); Thread.sleep(5 * 60 * 1000);
System.out.println("Server exiting");
System.exit(0);
}
}
客户端配置文件client.xml存放在demo.ws_addressing.client包下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cxf="http://cxf.apache.org/core"
xmlns:wsa="http://cxf.apache.org/ws/addressing" xmlns:http="http://cxf.apache.org/transports/http/configuration"
xsi:schemaLocation="http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 表示服务器端处理完成后,将结果返回给"http://localhost:9990/decoupled_endpoint"。 这个地址。如果直接返回给自己,则可将下面注释 -->
<http:conduit
name="{http://apache.org/hello_world_soap_http}SoapPort.http-conduit">
<http:client DecoupledEndpoint="http://localhost:9990/decoupled_endpoint" />
</http:conduit> <cxf:bus>
<cxf:features>
<wsa:addressing />
</cxf:features>
</cxf:bus>
</beans>
客户端访问类Client:
package demo.ws_addressing.client; import static org.apache.cxf.ws.addressing.JAXWSAConstants.CLIENT_ADDRESSING_PROPERTIES; import java.lang.reflect.UndeclaredThrowableException;
import java.net.URL;
import java.util.Map; import javax.xml.namespace.QName;
import javax.xml.ws.BindingProvider; import org.apache.cxf.Bus;
import org.apache.cxf.BusFactory;
import org.apache.cxf.bus.spring.SpringBusFactory;
import org.apache.cxf.ws.addressing.AddressingProperties;
import org.apache.cxf.ws.addressing.AttributedURIType;
import org.apache.cxf.ws.addressing.ObjectFactory;
import org.apache.hello_world_soap_http.Greeter;
import org.apache.hello_world_soap_http.PingMeFault;
import org.apache.hello_world_soap_http.SOAPService; public final class Client { private static final QName SERVICE_NAME = new QName(
"http://apache.org/hello_world_soap_http", "SOAPService");
private static final ObjectFactory WSA_OBJECT_FACTORY = new ObjectFactory();
private static final String USER_NAME = System.getProperty("user.name"); private Client() {
} public static void main(String args[]) throws Exception { try {
URL wsdlURL = Client.class.getClassLoader().getResource(
"hello_world_addr.wsdl");//加载wsdl文件 SpringBusFactory bf = new SpringBusFactory();
URL busFile = Client.class.getResource("client.xml");
Bus bus = bf.createBus(busFile.toString());
BusFactory.setDefaultBus(bus); SOAPService service = new SOAPService(wsdlURL, SERVICE_NAME);
Greeter port = service.getSoapPort(); implicitPropagation(port); // explicitPropagation(port); // implicitPropagation(port); } catch (UndeclaredThrowableException ex) {
ex.getUndeclaredThrowable().printStackTrace();
} catch (Throwable ex) {
ex.printStackTrace();
} finally {
System.exit(0);
}
} /**
* A series of invocations with implicitly propogated Message Addressing
* Properties.
*/
private static void implicitPropagation(Greeter port) {
System.out.println();
System.out.println("Implicit MessageAddressingProperties propagation");
System.out.println("------------------------------------------------"); System.out.println("Invoking sayHi...");
String resp = port.sayHi();
System.out.println("Server responded with: " + resp + "\n"); System.out.println("Invoking greetMe...");
resp = port.greetMe(USER_NAME);
System.out.println("Server responded with: " + resp + "\n"); System.out.println("Invoking greetMeOneWay...");
port.greetMeOneWay(USER_NAME);
System.out.println("No response from server as method is OneWay\n"); try {
System.out.println("Invoking pingMe, expecting exception...");
port.pingMe();
} catch (PingMeFault ex) {
System.out.println("Expected exception occurred: " + ex);
}
} private static AddressingProperties createMaps() {
// get Message Addressing Properties instance
AddressingProperties maps = new AddressingProperties(); // set MessageID property
AttributedURIType messageID = WSA_OBJECT_FACTORY
.createAttributedURIType();
messageID.setValue("urn:uuid:" + System.currentTimeMillis());
maps.setMessageID(messageID);
return maps;
} /**
* A series of invocations with explicitly propogated Message Addressing
* Properties.
*/
private static void explicitPropagation(Greeter port) {
System.out.println();
System.out.println("Explicit MessageAddressingProperties propagation");
System.out.println("------------------------------------------------"); // associate MAPs with request context
Map<String, Object> requestContext = ((BindingProvider) port)
.getRequestContext();
requestContext.put(CLIENT_ADDRESSING_PROPERTIES, createMaps()); System.out.println("Invoking sayHi...");
String resp = port.sayHi();
System.out.println("Server responded with: " + resp + "\n"); // set the RelatesTo property to the initial message ID, so that
// the series of invocations are explicitly related
// RelatesToType relatesTo = WSA_OBJECT_FACTORY.createRelatesToType();
// relatesTo.setValue(messageID.getValue());
// maps.setRelatesTo(relatesTo); System.out.println("Invoking greetMe...");
requestContext.put(CLIENT_ADDRESSING_PROPERTIES, createMaps());
resp = port.greetMe(USER_NAME);
System.out.println("Server responded with: " + resp + "\n"); System.out.println("Invoking greetMeOneWay...");
requestContext.put(CLIENT_ADDRESSING_PROPERTIES, createMaps());
port.greetMeOneWay(USER_NAME);
System.out.println("No response from server as method is OneWay\n"); // disassociate MAPs from request context
requestContext.remove(CLIENT_ADDRESSING_PROPERTIES);
}
}
分别运行Server类和Client类即可正常访问。通过tcpMon监听结果如下:
1、当client中没有指定<http:conduit>元素时:
请求:
响应
请求被处理后,结果返回给了原来的地址。
2、当client中指定了<http:conduit>元素时:
请求
该soap请求<soap:Header>中指定了处理完成后,将结果返回给特定的地址。
响应
响应为202,没有响应体。服务器已接受请求,但尚未处理。正如它可能被拒绝一样,最终该请求可能会也可能不会被执行。服务器接收到请求后,将处理后的结果转发给"http://localhost:9990/decoupled_endpoint" 这个地址。
cxf 消息寻址的更多相关文章
-
WCF - 消息
SOAP SOAP是Simple Object Access Protocol(简单对象访问协议)的简称 而如今SOAP已经成为了符合W3C制定的SOAP规范的消息 允许您使用 XML 在通过低层 I ...
-
RabbitMQ原理与相关操作(二)
接着 上篇随笔 增加几个概念: RabbitMQ是一个在AMQP(高级消息队列协议)标准基础上完整的,可服用的企业消息系统. AMQP模型的功能组件图(上图摘自 Sophia_tj 的 第2章 AMQ ...
-
ZLL网关程序分析
主机接口 zllSocCmd.h(ZLL的Socket主机接口) 此模块包含ZLL的Socket主机接口API.其包含的函数方法在zllSocCmd.c中实现 ZLL Soc Types 定义了描述设 ...
-
TI Zigbee Light Link 参考设计
TI Zigbee Light Link 参考设计 原文出处: http://processors.wiki.ti.com/index.php/Category:ZigBee_Light_Link ...
-
rabbitmq之基本原理及搭建单机环境
1.RabbitMQ基本原理 1.MQ全称Message Queue,是一种分布式应用程序的通信方法,是消费-生产者模型的典型代表,producer向消息队列中不断写入消息,而另一端consumer则 ...
-
中间件RabbitMQ之运维篇
一.RabbtMQ简介 RabbitMQ的官方站: http:/://www.rabbitmq.com/ rabbitMQ是一个在AMQP协议标准基础上完整的,可服用的企业 ...
-
RabbitMQ学习(一):RabbitMQ要点简介
转载:http://blog.csdn.net/leixiaotao_java/article/details/78909760#t0 1.什么是RabbitMQ? RabbitMQ是由Erlang语 ...
-
RabbitMQ介绍及安装部署
本节内容: RabbitMQ介绍 RabbitMQ运行原理 RabbitMQ重要术语 三种ExchangeType RabbitMQ集群种类 集群基本概念 镜像模式部署集群 一.RabbitMQ介绍 ...
-
RabbitMQ核心概念
AMQP的四个主要概念 1.虚拟主机(virtual host)或(vhost) 2.交换机(exchange) 3.队列(queue) 4.绑定器(bind) 什么是虚拟主机? 一组交换机.队列和绑 ...
随机推荐
-
非常有用!eclipse与myeclipse恢复已删除的文件和代码
eclipse与myeclipse恢复已删除的文件和代码 今天写了1300多行代码,被不小心删除了顿时感觉手足无措,后来用myeclipse的历史文件恢复功能,找回来了,虚惊一场!!!MyEclip ...
-
Django中的Model(字段)
Model Django中的model是用来操作数据库的,Model是一个ORM框架,我们只需要关心model的操作,而不需要关心到底是哪一种数据库. 一.基本知识: 数据库引擎: Django中自带 ...
-
UBER司机奖励政策
高峰时段: 早高峰:早6:30-8:30点 晚高峰:晚4:00-7:00点 *周六日只有晚高峰 其他时间均为平峰时段 滴滴快车单单2.5倍,注册地址:http://www.udache.com/如何注 ...
-
java之jvm学习笔记三(Class文件检验器)
java之jvm学习笔记三(Class文件检验器) 前面的学习我们知道了class文件被类装载器所装载,但是在装载class文件之前或之后,class文件实际上还需要被校验,这就是今天的学习主题,cl ...
-
eslint使用
参考文档 http://www.cnblogs.com/hahazexia/p/6393212.html http://blog.guowenfh.com/2016/08/07/ESLint-Rule ...
-
react中的DOM操作
前面的话 某些情况下需要在典型数据流外强制修改子代.要修改的子代可以是 React 组件实例,也可以是 DOM 元素.这时就要用到refs来操作DOM 使用场景 下面是几个适合使用 refs 的情况 ...
-
Apache ActiveMQ实战(2)-集群
ActiveMQ的集群 内嵌代理所引发的问题: 消息过载 管理混乱 如何解决这些问题--集群的两种方式: Master slave Broker clusters ActiveMQ的集群有两种方式: ...
-
#3 Python面向对象(二)
前言 上一节主要记录面向对象编程的思想以及Python类的简单创建,这节继续深入类中变量的相关知识,Here we go! Python中类的各种变量 1.1 类变量 类变量定义:在类中,在函数体(方 ...
-
centos 7下rabbitmq安装(转)
安装erlang环境 添加rabbitmq依赖的erlang yum命令repos # In /etc/yum.repos.d/rabbitmq-erlang.repo [rabbitmq-erlan ...
-
初始MapReduce
MapReduce 概述 MapReduce是一个分布式运算程序的编程框架,是用户开发“基于Hadoop的数据分析应用"的核心框架 MapReduce核心功能是将用户编写的业务逻辑代码和自带 ...