zoukankan      html  css  js  c++  java
  • 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 + "
    ");
            return "Hello " + me;
        }
    
        public void greetMeOneWay(String me) {
            LOG.info("Executing operation greetMeOneWay");
            System.out.println("Executing operation greetMeOneWay
    ");
            System.out.println("Hello there " + me);
        }
    
        public String sayHi() {
            LOG.info("Executing operation sayHi");
            System.out.println("Executing operation sayHi
    ");
            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
    ");
            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 + "
    ");
    
            System.out.println("Invoking greetMe...");
            resp = port.greetMe(USER_NAME);
            System.out.println("Server responded with: " + resp + "
    ");
    
            System.out.println("Invoking greetMeOneWay...");
            port.greetMeOneWay(USER_NAME);
            System.out.println("No response from server as method is OneWay
    ");
    
            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 + "
    ");
    
            // 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 + "
    ");
    
            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
    ");
    
            // 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"  这个地址。

  • 相关阅读:
    文档库文件上传Webpart(原创)
    SharePointWebControls帮助类
    使用反射创建动态程序集
    Silverlight Workflow 工作流设计器和工作流编辑器的若干截图,先睹为快(Workflow Designer)
    Using Networking to Retrieve Data and Populate a DataGrid
    昕友silverlight表单设计器的使用 (原创 Form Designer)
    Bing翻译和Google翻译的比较
    具有某接口与是某类型
    UI Automation in WPF/Silverlight
    RTP/RTCP/RTSP/SIP/SDP
  • 原文地址:https://www.cnblogs.com/always-online/p/4232031.html
Copyright © 2011-2022 走看看