zoukankan      html  css  js  c++  java
  • webservice05#soap消息

    1, SOAPMessage结构图

    2, SOAP消息的创建

      1>前面的一个简单WebService  服务

    package com.yangw.soap.service;
    
    import javax.jws.WebParam;
    import javax.jws.WebResult;
    import javax.jws.WebService;
    
    //说明该接口是服务接口,可以指定我们自己的命名空间
    @WebServicepublic interface IMyService {
    
        /**
         * 使用注解指明返回值名,参数名
         */
         @WebResult(name="addResult")
         public int add(@WebParam(name="a")int a,@WebParam(name="b")int b);
    }
    package com.yangw.soap.service;
    
    import javax.jws.WebService;
    
    //说明该类是服务接口的实现类
    @WebService(endpointInterface="com.yangw.soap.service.IMyService")
    public class MyServiceImpl implements IMyService {
    
        @Override
        public int add(int a, int b) {
            System.out.println("a+b="+(a+b));
            return a+b;
        }
    
    }
    package com.yangw.soap.service;
    
    import javax.xml.ws.Endpoint;
    
    public class MyService {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            //发布服务
            Endpoint.publish("http://localhost:8899/ns", new MyServiceImpl());
        }
     
    }

     

     2>SOAPMessage的创建

    package com.yangw.soap.test;
    
    import java.io.IOException;
    
    import javax.xml.namespace.QName;
    import javax.xml.soap.MessageFactory;
    import javax.xml.soap.SOAPBody;
    import javax.xml.soap.SOAPBodyElement;
    import javax.xml.soap.SOAPEnvelope;
    import javax.xml.soap.SOAPException;
    import javax.xml.soap.SOAPMessage;
    import javax.xml.soap.SOAPPart;
    
    import org.junit.Test;
    
    public class TestSoap {
    
        /**
         * 自己创建soap协议
         */
        @Test
        public void test() {
            
            try {
                //1,创建消息工厂
                MessageFactory factory=MessageFactory.newInstance();
                //2,根据消息工厂创建soap消息
                SOAPMessage msg=factory.createMessage();
                //3,创建SOAPPart
                SOAPPart part=msg.getSOAPPart();
                //4,获取soapEnvelope
                SOAPEnvelope envelope=part.getEnvelope();
                //5,通过SOAPEnvelope可以有效的获取相应的Header和Body等
                SOAPBody body=envelope.getBody();
                //6,根据QName创建相应的节点(QName就是一个带有命名空间的节点)
                QName qName=new QName("http://service.soap.yangw.com/",
                        "add", "ns"); //相当于<ns:add xmlns="http://service.soap.yangw.com/" />
                //7,将QName加入到body中
    //            body.addBodyElement(qName).setValue("123123");
                /**
                 * <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
                 *     <SOAP-ENV:Header/>
                 *     <SOAP-ENV:Body>
                 *         <ns:add xmlns:ns="http://service.soap.yangw.com/">123123</ns:add>
                 *     </SOAP-ENV:Body>
                 * </SOAP-ENV:Envelope>
                 */
                //如果使用下面注释住的这个方式,会将<>转换为&lt;&gt;
                //body.addBodyElement(qName).setValue("<a>11</a><b>22</b>");
                //加子元素
                SOAPBodyElement bodyEle=body.addBodyElement(qName);
                bodyEle.addChildElement("a").setValue("11");
                bodyEle.addChildElement("b").setValue("22");
                
                
                //打印消息
                msg.writeTo(System.out);
                
                /**
                 * <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
                 *     <SOAP-ENV:Header/>
                 *     <SOAP-ENV:Body>
                 *         <ns:add xmlns:ns="http://service.soap.yangw.com/">
                 *             <a>11</a>
                 *             <b>22</b>
                 *         </ns:add>
                 *     </SOAP-ENV:Body>
                 * </SOAP-ENV:Envelope>
                 */
            } catch (SOAPException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
    }

     3, SOAPMessage的传递

        private String ns="http://service.soap.yangw.com/";
        private String wsdlUrl="http://localhost:8899/ns?wsdl";
        
        /**
         * Soap消息的传递
         */
        @Test
        public void test02() {
            
            try {
                //1,创建服务
                URL url=new URL(wsdlUrl);
                QName qName=new QName(ns,"MyServiceImplService");
                Service service=Service.create(url, qName);
                
                //2,创建Dispatch    
                Dispatch<SOAPMessage> dispatch=service.createDispatch(new QName(ns,"MyServiceImplPort"),//(创建Port的时候指定名称空间)
                        SOAPMessage.class, Service.Mode.MESSAGE);
        
                //3, 创建SOAPMessage
                 SOAPMessage msg=MessageFactory.newInstance().createMessage();
                 SOAPEnvelope envelope=msg.getSOAPPart().getEnvelope();
                 SOAPBody body=envelope.getBody();
                
                 //4, 创建QName来指定消息中传递的数据
                 QName eName=new QName(ns,"add", "nn"); //前缀必须指定,名字可以任意 <nn:add xmlns="XXX" />
                 SOAPBodyElement bodyEle=body.addBodyElement(eName);
                 bodyEle.addChildElement("a").setValue("22");
                 bodyEle.addChildElement("b").setValue("33");
                 
                 msg.writeTo(System.out); //输出消息到控制台
                 /**
                  * <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
                  *     <SOAP-ENV:Header/>
                  *     <SOAP-ENV:Body>
                  *         <nn:add xmlns:nn="http://service.soap.yangw.com/">
                  *             <a>22</a>
                  *             <b>33</b>
                  *         </nn:add>
                  *     </SOAP-ENV:Body>
                  * </SOAP-ENV:Envelope>
                  */
                 System.out.println("
     invoke ...");
                 //5, 通过Dispatch传递消息
                 SOAPMessage  resMsg= dispatch.invoke(msg);
                 resMsg.writeTo(System.out);
                 /**
                  * <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
                  *     <S:Header/>
                  *     <S:Body>
                  *         <ns2:addResponse xmlns:ns2="http://service.soap.yangw.com/">
                  *             <addResult>55</addResult>
                  *         </ns2:addResponse>
                  *     </S:Body>
                  * </S:Envelope>
                  */
                 //6, 将响应的消息转换为DOM对象
                 Document doc=resMsg.getSOAPPart().getEnvelope().getBody().extractContentAsDocument();
    String str
    =doc.getElementsByTagName("addResult").item(0).getTextContent(); System.out.println(" "+str); } catch (SOAPException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }

     4, 基于PayLoad的方式传递SOAP消息,其实是附件的形式  下面实例是传递了一个自定义User对象 它可以传递字符串

    package com.yangw.soap.service;
    
    import java.util.Date;
    
    import javax.xml.bind.annotation.XmlRootElement;
    
    @XmlRootElement
    public class User {
    
        private String userName;
        private String password;
        private int age;
        private Date birthday;
        
        
        public User() {
            super();
        }
        public User(String userName, String password, int age, Date birthday) {
            super();
            this.userName = userName;
            this.password = password;
            this.age = age;
            this.birthday = birthday;
        }
        
        public String getUserName() {
            return userName;
        }
        public void setUserName(String userName) {
            this.userName = userName;
        }
        public String getPassword() {
            return password;
        }
        public void setPassword(String password) {
            this.password = password;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public Date getBirthday() {
            return birthday;
        }
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
        
        
    }
    package com.yangw.soap.service;
    
    import java.util.List;
    
    import javax.jws.WebParam;
    import javax.jws.WebResult;
    import javax.jws.WebService;
    
    //说明该接口是服务接口
    @WebService
    public interface IMyService {
    
        /**
         * 使用注解指明返回值名,参数名
         */
         @WebResult(name="addResult")
         public int add(@WebParam(name="a")int a,@WebParam(name="b")int b);
         
         //返回对象是什么类型就写什么值,不区分单个对象还是List
         @WebResult(name="user")
         public User addUser(@WebParam(name="user")User user);
         @WebResult(name="user")
         public User login(@WebParam(name="username")String username,@WebParam(name="password")String password);
         
         @WebResult(name="user")
         public List<User> list();
         
         
    }
    package com.yangw.soap.service;
    
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    
    import javax.jws.WebService;
    
    //说明该类是服务接口的实现类
    @WebService(endpointInterface="com.yangw.soap.service.IMyService")
    public class MyServiceImpl implements IMyService {
    
        private static List<User> users=new ArrayList<User>();
        static{
            users.add(new User("yangw","123456",12,new Date()));
            users.add(new User("awei","123456",25,new Date()));
        }
        
        @Override
        public int add(int a, int b) {
            System.out.println("a+b="+(a+b));
            return a+b;
        }
    
        @Override
        public User addUser(User user) {
            users.add(user);
            return user;
        }
    
        @Override
        public User login(String username, String password) {
            for(User user:users){
                if(user.getUserName().equals(username)&&user.getPassword().equals(password)){
                    return user;
                }
            }
            return null;
        }
    
        @Override
        public List<User> list() {
            return users;
        }
    
    }

      真正的处理消息的组成,发送和接收

        /**
         * Soap消息的传递,PAYLOAD方式可以传字符串的.
         */
        @Test
        public void test03() {
            
            try {
                //1,创建服务
                URL url=new URL(wsdlUrl);
                QName qName=new QName(ns,"MyServiceImplService");
                Service service=Service.create(url, qName);
                
                //2,创建Dispatch ,通过Source的方式传递
                Dispatch<Source> dispatch=service.createDispatch(new QName(ns,"MyServiceImplPort"),
                        Source.class, Service.Mode.PAYLOAD);
        
                //3, 根据用户对象创建相应的xml(编排)
                User user=new User("ahuang","123321",23,new Date());
                JAXBContext ctx=JAXBContext.newInstance(User.class);
                Marshaller mar=ctx.createMarshaller();
                    //去掉文档头和尾
                mar.setProperty(Marshaller.JAXB_FRAGMENT, true);
                StringWriter writer=new StringWriter();
                mar.marshal(user, writer);
                    
                //4,封装相应的Part addUser
                String payLoad="<nn:addUser xmlns:nn='"+ns+"'>"+writer.toString()+"</nn:addUser>";
                System.out.println(payLoad);
                
                //5,通过Dispatch传递 payLoad
                Source response=dispatch.invoke(new StreamSource(new StringReader(payLoad)));
            
                //6, 将Source转换为DOM操作,使用Transform对象
                Transformer tran=TransformerFactory.newInstance().newTransformer();
                DOMResult result=new DOMResult();
                tran.transform(response, result);
                
                //7,处理响应信息
                XPath xpath=XPathFactory.newInstance().newXPath();
                NodeList nl=(NodeList) xpath.evaluate("//user", result.getNode(),XPathConstants.NODESET);
                    //反编排
                User u=(User) ctx.createUnmarshaller().unmarshal(nl.item(0));
                System.out.println(u.getUserName());
                
            } catch (IOException e) {
                e.printStackTrace();
            } catch (JAXBException e) {
                e.printStackTrace();
            } catch (TransformerConfigurationException e) {
                e.printStackTrace();
            } catch (TransformerFactoryConfigurationError e) {
                e.printStackTrace();
            } catch (TransformerException e) {
                e.printStackTrace();
            } catch (XPathExpressionException e) {
                e.printStackTrace();
            }
        }

     5, list方法测试

    package com.yangw.soap.service;
    
    import java.util.List;
    
    import javax.jws.WebParam;
    import javax.jws.WebResult;
    import javax.jws.WebService;
    
    //说明该接口是服务接口
    @WebService
    public interface IMyService {
    
        /**
         * 使用注解指明返回值名,参数名
         */
         @WebResult(name="addResult")
         public int add(@WebParam(name="a")int a,@WebParam(name="b")int b);
         
         //返回对象是什么类型就写什么值,不区分单个对象还是List
         @WebResult(name="user")
         public User addUser(@WebParam(name="user")User user);
         @WebResult(name="user")
         public User login(@WebParam(name="username")String username,@WebParam(name="password")String password);
         
         @WebResult(name="user")
         public List<User> list1();
         
         @WebResult(name="user")
         //设置header为true,让它以头信息的形式传递
         //这是显示的方式传递头部信息的方式
         public List<User> list2(@WebParam(name="authInfo",header=true)String authInfo);
         
    }

      不带参数的list()方法

    /**
         * Soap消息的传递  --测试 list()方法,不带参数的形式
         */
        @Test
        public void test04() {
            
            try {
                //1,创建服务
                URL url=new URL(wsdlUrl);
                QName qName=new QName(ns,"MyServiceImplService");
                Service service=Service.create(url, qName);
                
                //2,创建Dispatch    (创建Port的时候指定名称空间)
                Dispatch<SOAPMessage> dispatch=service.createDispatch(new QName(ns,"MyServiceImplPort"),
                        SOAPMessage.class, Service.Mode.MESSAGE);
        
                //3, 创建SOAPMessage
                 SOAPMessage msg=MessageFactory.newInstance().createMessage();
                 SOAPEnvelope envelope=msg.getSOAPPart().getEnvelope();
                 SOAPBody body=envelope.getBody();
                
                 //4, 创建QName来指定消息中传递的数据
                 QName eName=new QName(ns,"list1", "nn"); //前缀必须指定,名字可以任意 <nn:add xmlns="XXX" />
                 body.addBodyElement(eName);
                
                 msg.writeTo(System.out); //输出消息到控制台
                 /**
                   *<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
                   *    <SOAP-ENV:Header/>
                   *    <SOAP-ENV:Body>
                   *        <nn:list xmlns:nn="http://service.soap.yangw.com/"/>
                   *    </SOAP-ENV:Body>
                   *</SOAP-ENV:Envelope>
                   */
                 System.out.println("
     invoke ...");
                 //5, 通过Dispatch传递消息
                 SOAPMessage  resMsg= dispatch.invoke(msg);
                 resMsg.writeTo(System.out);
                 System.out.println();
                 /**
                  *<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
                  *    <S:Header/>
                  *    <S:Body>
                  *  <ns2:listResponse xmlns:ns2="http://service.soap.yangw.com/">
                  *   <user>
                  *     <age>12</age>
                  *        <birthday>2014-03-03T14:21:02.468+08:00</birthday>
                  *        <password>123456</password>
                  *        <userName>yangw</userName>
                  *    </user>
                  *   <user>
                  *       <age>25</age>
                  *       <birthday>2014-03-03T14:21:02.468+08:00</birthday>
                  *       <password>123456</password>
                  *       <userName>awei</userName>
                  *   </user>
                  *  </ns2:listResponse>
                  * </S:Body>
                  *</S:Envelope>
                  */
                 //6, 将响应的消息转换为DOM对象
                 Document doc=resMsg.getSOAPPart().getEnvelope().getBody().extractContentAsDocument();
                 NodeList nl=doc.getElementsByTagName("user");
                 
                 JAXBContext ctx=JAXBContext.newInstance(User.class);
                 
                 for(int i=0;i<nl.getLength();i++){
                     Node node=nl.item(i); //import org.w3c.dom.Node;
                     User user=(User) ctx.createUnmarshaller().unmarshal(node);
                     System.out.println(user.getUserName()+":"+user.getPassword());
                 }
            } catch (SOAPException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (JAXBException e) {
                e.printStackTrace();
            }
        }

      带参数的list()方法测试

    /**
         * Soap消息的传递  --测试 list(String)方法,带参数的形式,一般都是把参数放到头信息中作验证
         */
        @Test
        public void test05() {
            
            try {
                //1,创建服务
                URL url=new URL(wsdlUrl);
                QName qName=new QName(ns,"MyServiceImplService");
                Service service=Service.create(url, qName);
                
                //2,创建Dispatch    (创建Port的时候指定名称空间)
                Dispatch<SOAPMessage> dispatch=service.createDispatch(new QName(ns,"MyServiceImplPort"),
                        SOAPMessage.class, Service.Mode.MESSAGE);
        
                //3, 创建SOAPMessage
                 SOAPMessage msg=MessageFactory.newInstance().createMessage();
                 SOAPEnvelope envelope=msg.getSOAPPart().getEnvelope();
                
                 //3.2 头信息的处理
                 SOAPHeader header=envelope.getHeader();
                 if(header==null)
                     header=envelope.addHeader();
                 QName hName=new QName(ns,"authInfo", "nn");
                 header.addHeaderElement(hName).setValue("aabbcc");
                 
                 SOAPBody body=envelope.getBody();
                
                 //4, 创建QName来指定消息中传递的数据
                 QName eName=new QName(ns,"list2", "nn"); //前缀必须指定,名字可以任意 <nn:add xmlns="XXX" />
                 body.addBodyElement(eName);
                
                 msg.writeTo(System.out); //输出消息到控制台
                /**
                 *  <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
                 *   <SOAP-ENV:Header>
                 *    <nn:authInfo xmlns:nn="http://service.soap.yangw.com/">aabbcc</nn:authInfo>
                 *   </SOAP-ENV:Header>
                 *   <SOAP-ENV:Body>
                 *    <nn:list2 xmlns:nn="http://service.soap.yangw.com/"/>
                 *   </SOAP-ENV:Body>
                 *  </SOAP-ENV:Envelope>
                 */
                 System.out.println("
     invoke ...");
                 //5, 通过Dispatch传递消息
                 SOAPMessage  resMsg= dispatch.invoke(msg);
                 resMsg.writeTo(System.out);
                 System.out.println();
                 /**
                  *<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
                  *    <S:Header/>
                  *    <S:Body>
                  *  <ns2:listResponse xmlns:ns2="http://service.soap.yangw.com/">
                  *   <user>
                  *     <age>12</age>
                  *        <birthday>2014-03-03T14:21:02.468+08:00</birthday>
                  *        <password>123456</password>
                  *        <userName>yangw</userName>
                  *    </user>
                  *   <user>
                  *       <age>25</age>
                  *       <birthday>2014-03-03T14:21:02.468+08:00</birthday>
                  *       <password>123456</password>
                  *       <userName>awei</userName>
                  *   </user>
                  *  </ns2:listResponse>
                  * </S:Body>
                  *</S:Envelope>
                  */
                 //6, 将响应的消息转换为DOM对象
                 Document doc=resMsg.getSOAPPart().getEnvelope().getBody().extractContentAsDocument();
                 NodeList nl=doc.getElementsByTagName("user");
                 
                 JAXBContext ctx=JAXBContext.newInstance(User.class);
                 
                 for(int i=0;i<nl.getLength();i++){
                     Node node=nl.item(i); //import org.w3c.dom.Node;
                     User user=(User) ctx.createUnmarshaller().unmarshal(node);
                     System.out.println(user.getUserName()+":"+user.getPassword());
                 }
            } catch (SOAPException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (JAXBException e) {
                e.printStackTrace();
            }
        }

      上面头消息的处理是显示消息的处理,用wsimport导出之后,可以看到会“自动生成一个List对象” 

         接口上的名称空间应该与实现类上的名称空间一致.

    ----------- 赠人玫瑰,手有余香     如果本文对您有所帮助,动动手指扫一扫哟   么么哒 -----------


    未经作者 https://www.cnblogs.com/xin1006/ 梦相随1006 同意,不得擅自转载本文,否则后果自负
  • 相关阅读:
    社区专家谈 12306
    一致性Hash算法(分布式算法)
    ASP.NET二级域名站点共享Session状态
    树莓派2 安装 win10Iot 和 Ubuntu mate
    Maven运行时异常java.lang.UnsupportedClassVersionError的解决方案
    Ubuntu安装steam游戏平台的解决方案
    Spring配置JNDI的解决方案
    Intellij Idea无法从Controller跳转到视图页面的解决方案
    电话激活windows server 2012的解决方案
    如何下载Red Hat Enterprise Linux系统
  • 原文地址:https://www.cnblogs.com/xin1006/p/3571807.html
Copyright © 2011-2022 走看看