cxf 消息寻址
一、消息寻址
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) 什么是虚拟主机? 一组交换机.队列和绑 ...
随机推荐
- 重构第18天 用条件语句来代替异常(Replace exception with conditional)
理解:本文中的“使用条件判断代替异常”是指把没有必要使用异常做判断的条件尽量改为条件判断. 详解: 重构前代码: public class Microwave { private IMicrowave ...
- .Net 配置文件——继承ConfigurationSection实现自定义处理类处理自定义配置节点
除了使用继承IConfigurationSectionHandler的方法定义处理自定义节点的类,还可以通过继承ConfigurationSection类实现同样效果. 首先说下.Net配置文件中一个 ...
- 【原创】Silverlight客户端发起WebRequest请求分析
Silverlight网站部署后,客户端浏览器访问的时候会 下载 网站的xap文件包等信息,把程序代码放到本地执行,因为本地机器上安装了silverlight运行库. 所以如果silverlight前 ...
- 用c#写的一个局域网聊天客户端 类似小飞鸽
用c#写的一个局域网聊天客户端 类似小飞鸽 摘自: http://www.cnblogs.com/yyl8781697/archive/2012/12/07/csharp-socket-udp.htm ...
- Python打包-py2exe使用
Py2exe 64位下载地址:http://download.csdn.net/detail/henujyj/8532827 Py2exe 32位下载地址:https://sourceforge.ne ...
- C#中弹出文件选择窗体和判断是否下载提示窗体的源码
1.创建一个window窗体
- 数据库sqlserver2008登陆名密码登陆不了怎么办?
我用的是sql server2008数据库,原先创建的登录名是sa,但是密码就忘了.总是出现这个连接问题
- asp.net中,<%#%>,<%=%>和<%%>分别是什么意思,有什么区别
在asp.net中经常出现包含这种形式<%%>的html代码,总的来说包含下面这样几种格式:一. <%%>这种格式实际上就是和asp的用法一样的,只是asp中里面是vbscr ...
- php获取textarea的值并处理回车换行的方法
//注:\n是用双引号包的的,双引号!!双引号!!! explode("\n",$row[0]['value']
- ArrayList,Hashtable,List<T>,Dictionary<K,V>
1.ArrayList ArrayList list = new ArrayList(); //for遍历 ; i < list.Count; i++) { SE se=(SE)list[i]; ...