zoukankan      html  css  js  c++  java
  • webservice系统学习笔记5-手动构建/发送/解析SOAP消息

    手动拼接SOAP消息调用webservice

    SOAP消息的组成:

     

    1、创建需要发送的SOAP消息的XML(add方法为例子)

    /**
         * 创建访问add方法的SOAP消息的xml
         */
        @Test
        public void test1(){
            try {
                //1、创建消息工厂
                MessageFactory factory = MessageFactory.newInstance();
                //2、根据消息工厂创建SoapMessage
                SOAPMessage message = factory.createMessage();
                //3、创建SOAPPart
                SOAPPart part = message.getSOAPPart();
                //4、获取SOAPENvelope
                SOAPEnvelope envelope = part.getEnvelope();
                //5、可以通过SoapEnvelope有效的获取相应的Body和Header等信息
                SOAPBody body = envelope.getBody();
                //6、根据Qname创建相应的节点(QName就是一个带有命名空间的)
                QName qname = new QName("http://ws01.yzl.com", 
                        "add","ns");//<ns:add xmlns:ns=http://ws01.yzl.com>这里指定ns是前缀,必须指定,随便定义即可,不定义这消息将无效
                //如果使用以下方式进行设置,会见<>转换为&lt;和&gt
                //body.addBodyElement(qname).setValue("<a>1</a><b>2</b>");
                SOAPBodyElement ele = body.addBodyElement(qname);
                ele.addChildElement("a").setValue("22");
                ele.addChildElement("b").setValue("33");
                //打印消息信息
                message.writeTo(System.out);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    结果为下:

    <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Header/>
    <SOAP-ENV:Body><ns:add xmlns:ns="http://ws01.yzl.com"><a>22</a><b>33</b></ns:add>
    </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>

    2、提交创建的SOAP消息的xml到服务器端与其进行通信

    2.1、使用SOAPMessage和Service.Mode.MESSAGE的方式发送消息

    /**
         * 发送add方法的SOAP的消息并接受解析返回的soap消息(使用Service.Mode.MESSAGE模式进行发送数据)
          <service name="MyServiceImplService">
              <port name="MyServiceImplPort" binding="tns:MyServiceImplPortBinding">
                  <soap:address location="http://localhost:8888/ws01" /> 
              </port>
          </service>
         * 
         */
        @Test
        public void test2(){
            try {
                String namespace = "http://ws01.yzl.com/";
                String wsdlUrl = "http://localhost:8888/ws01?wsdl";
            
                //1、创建服务(Service)
                URL url = new URL(wsdlUrl);
                QName qname = new QName(namespace,"MyServiceImplService");
                Service service = Service.create(url, qname);
                
                //2、创建Dispatch
                //public interface Dispatch<T>extends BindingProviderDispatch 接口提供对动态调用服务端点操作的支持。javax.xml.ws.Service 接口作为创建 Dispatch 实例的工厂。 
                Dispatch<SOAPMessage> dispatch = service.createDispatch(new QName(namespace,"MyServiceImplPort"), SOAPMessage.class, Service.Mode.MESSAGE);
                
                //3、创建SOAPMessage
                MessageFactory factory = MessageFactory.newInstance();
                SOAPMessage message = factory.createMessage();
                SOAPPart part = message.getSOAPPart();
                SOAPEnvelope envelope = part.getEnvelope();
                SOAPBody body = envelope.getBody();
                QName portQname = new QName("http://ws01.yzl.com/", 
                        "add","ns");
                SOAPBodyElement ele = body.addBodyElement(portQname);
                ele.addChildElement("a").setValue("22");
                ele.addChildElement("b").setValue("33");
                
                //4、通过Dispatch传递消息,并返回响应消息
                SOAPMessage returnMessage = dispatch.invoke(message);
                returnMessage.writeTo(System.out);//打印返回消息
                System.out.println();
                
                //5、解析返回的SOAP消息的XML
                Document doc = returnMessage.getSOAPBody().extractContentAsDocument();
                //Document doc = returnMessage.getSOAPPart().getEnvelope().getBody().extractContentAsDocument();
                String result = doc.getElementsByTagName("addResult").item(0).getTextContent();
                System.out.println("result is :" + result);
                
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    结果:

    <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Header/>
    <S:Body>
    <ns2:addResponse xmlns:ns2="http://ws01.yzl.com/"><addResult>55</addResult></ns2:addResponse>
    </S:Body>
    </S:Envelope>
    result is :55

    2.2、使用Source和Service.Mode.PAYLOAD的方式来发送消息

    接口IMyService.java中添加方法:

    /**
    *这里将WebResult和WebParam定义为user是为了使用jaxb进行类的编排和反编排时方便
    */
    @WebResult(name="user")
    public List<User> getChildListByUser(@WebParam(name="user")User user);
    @Override
    public List<User> getChildListByUser(User user) {
      List<User> result = new ArrayList<User>();
      result.add(new User("张三", "11111"));
      result.add(new User("李四", "22222"));
      return result;
    }

    这时wsdl中的定义如下:

    调用代码:

    /**
         * 使用Source和Service.Mode.PAYLOAD的方式来发送消息
         * 使用JAXB来对User对象进行编排和反编排
         * 使用xpath解析xml
         * @throws Exception
         */
        @Test
        public void test3() throws Exception{
            String namespace = "http://ws01.yzl.com/";
            String wsdlUrl = "http://localhost:8888/ws01?wsdl";
        
            //1、创建服务(Service)
            URL url = new URL(wsdlUrl);
            QName qname = new QName(namespace,"MyServiceImplService");
            Service service = Service.create(url, qname);
            
            //2、创建Dispatch(通过源数据的方式传递)
            Dispatch<Source> dispatch = service.createDispatch(new QName(namespace,"MyServiceImplPort"),Source.class, Service.Mode.PAYLOAD);
            
            //3、根据用户对象创建相应的xml(user对象的属性可以通过wsdl文件构建出来)
            User user = new User("管理员","123456");
            JAXBContext jaxb = JAXBContext.newInstance(User.class);
            Marshaller ms = jaxb.createMarshaller();
            ms.setProperty(Marshaller.JAXB_FRAGMENT, true);//去掉xml声明
            StringWriter writer = new StringWriter();
            ms.marshal(user, writer);
            //System.out.println(writer.toString());//<user><password>123456</password><username>管理员</username></user>
            
            //4、封装相应的part addUser
            String payload = "<nn:getChildListByUser xmlns:nn=""+namespace+"">"+writer.toString()+"</nn:getChildListByUser>";
            System.out.println(payload);
            StreamSource rs = new StreamSource(new StringReader(payload));
            
            //5、通过dispatch传递payload
            Source response = (Source)dispatch.invoke(rs);
            
            //6、将Source转化为DOM进行操作,使用Transform对象转换
            Transformer tran = TransformerFactory.newInstance().newTransformer();
            DOMResult result = new DOMResult();
            tran.transform(response, result);
            
            //7、处理相应信息(通过xpath处理)
            XPath xpath = XPathFactory.newInstance().newXPath();
            NodeList nl = (NodeList)xpath.evaluate("//user", result.getNode(),XPathConstants.NODESET);
            for(int i=0; i<nl.getLength(); i++){
                User ru = (User)jaxb.createUnmarshaller().unmarshal(nl.item(i));
                System.out.println(ru.getUsername());
            }
        }

    结果如下:

    <nn:getChildListByUser xmlns:nn="http://ws01.yzl.com/"><user><password>123456</password><username>管理员</username></user></nn:getChildListByUser>
    张三
    李四

      

  • 相关阅读:
    java多态课后作业
    java继承与接口课后作业
    java数组课后作业
    javaString课后作业
    Java类与对象课后作业
    java方法课后作业
    java基本知识课后作业
    读《大道至简》第二章有感
    课堂作业(字符串转化并计算)
    读《大道至简》第一章有感
  • 原文地址:https://www.cnblogs.com/yangzhilong/p/3282951.html
Copyright © 2011-2022 走看看