一、消息寻址

  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 消息寻址的更多相关文章

  1. WCF - 消息

    SOAP SOAP是Simple Object Access Protocol(简单对象访问协议)的简称 而如今SOAP已经成为了符合W3C制定的SOAP规范的消息 允许您使用 XML 在通过低层 I ...

  2. RabbitMQ原理与相关操作(二)

    接着 上篇随笔 增加几个概念: RabbitMQ是一个在AMQP(高级消息队列协议)标准基础上完整的,可服用的企业消息系统. AMQP模型的功能组件图(上图摘自 Sophia_tj 的 第2章 AMQ ...

  3. ZLL网关程序分析

    主机接口 zllSocCmd.h(ZLL的Socket主机接口) 此模块包含ZLL的Socket主机接口API.其包含的函数方法在zllSocCmd.c中实现 ZLL Soc Types 定义了描述设 ...

  4. TI Zigbee Light Link 参考设计

    TI  Zigbee Light Link 参考设计 原文出处: http://processors.wiki.ti.com/index.php/Category:ZigBee_Light_Link ...

  5. rabbitmq之基本原理及搭建单机环境

    1.RabbitMQ基本原理 1.MQ全称Message Queue,是一种分布式应用程序的通信方法,是消费-生产者模型的典型代表,producer向消息队列中不断写入消息,而另一端consumer则 ...

  6. 中间件RabbitMQ之运维篇

    一.RabbtMQ简介        RabbitMQ的官方站: http:/://www.rabbitmq.com/        rabbitMQ是一个在AMQP协议标准基础上完整的,可服用的企业 ...

  7. RabbitMQ学习(一):RabbitMQ要点简介

    转载:http://blog.csdn.net/leixiaotao_java/article/details/78909760#t0 1.什么是RabbitMQ? RabbitMQ是由Erlang语 ...

  8. RabbitMQ介绍及安装部署

    本节内容: RabbitMQ介绍 RabbitMQ运行原理 RabbitMQ重要术语 三种ExchangeType RabbitMQ集群种类 集群基本概念 镜像模式部署集群 一.RabbitMQ介绍 ...

  9. RabbitMQ核心概念

    AMQP的四个主要概念 1.虚拟主机(virtual host)或(vhost) 2.交换机(exchange) 3.队列(queue) 4.绑定器(bind) 什么是虚拟主机? 一组交换机.队列和绑 ...

随机推荐

  1. struts2重点——ModelDriven

    一.属性驱动 在目标 Action 类中,通过 setXxx() 方法来接收请求参数. 二.模型驱动 1.ParametersInterceptor 拦截器工作原理 ParametersInterce ...

  2. Mybatis 示例之 foreach

    foreach一共有三种类型,分别为List,[](array),Map三种. foreach的第一篇用来将List和数组(array). 下面表格是我总结的各个属性的用途和注意点. foreach属 ...

  3. Qt Style Sheet实践(一):按钮及关联菜单

    导读 正如web前端开发中CSS(Cascade Style Sheet)的作用一样,Qt开发中也可以使用修改版的QSS将逻辑业务和用户界面进行隔离.这样,美工设计人员和逻辑实现者可以各司其职而不受干 ...

  4. 重构第31天 使用多态替代条件语句( Replace conditional with Polymorphism)

    理解:本文中的”使用多态代替条件判断”是指如果你需要检查对象的类型或者根据类型执行一些操作时,一种很好的办法就是将算法封装到类中,并利用多态性进行抽象调用. 详解:本文展示了面向对象编程的基础之一“多 ...

  5. .net中清理内存,清理占用内存方式方法

    #region 内存回收 [DllImport("kernel32.dll", EntryPoint = "SetProcessWorkingSetSize") ...

  6. C#基本概念列举说明

    1. 关键字      在C#代码中常常使用关键字,关键字也叫保留字,是对C#有特定意义的字符串.关键字在Visual Studio 环境的代码视图中默认以蓝色显示.例如,代码中的using.name ...

  7. C#初入串口通信(串行通信)总结

    使用WinFrom来实现: 首先要知道串口通信协议以及原理 原理大概提一下:要自己翻阅看.(http://book.51cto.com/art/200911/162532.htm或者http://hi ...

  8. java初始化构造函数调用顺序

    类初始化时构造函数调用顺序: (1)初始化对象的存储空间为零或null值:  (2)调用父类构造函数:  (3)按顺序分别调用类成员变量和实例成员变量的初始化表达式:  (4)调用本身构造函数. 例子 ...

  9. Liunx目录结构

    /bin: bin是Binary的缩写, 这个目录存放着最经常使用的命令. /boot:这里存放的是启动Linux时使用的一些核心文件,包括一些连接文件以及镜像文件. /dev :dev是Device ...

  10. jQuery中each()、find()、filter()等节点操作方法

    1.each(callback) 官方解释: 返回值:jQuery 概述 以每一个匹配的元素作为上下文来执行一个函数. 意味着,每次执行传递进来的函数时,函数中的this关键字都指向一个不同的DOM元 ...