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("\n 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("\n"+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("\n 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("\n 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对象”

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

webservice05#soap消息的更多相关文章

  1. 如何用Apache TCPMon来截获SOAP消息

    在WebService服务器和客户机之间会传递SOAP消息,有时我们需要得到这些消息以便调试,而Apache的TCPMon可以帮助我们做到这一点.  TCPMon的下载地址在http://ws.apa ...

  2. soap消息机制 讲解

    SOAP(Simple Object Access Protocol,简单对象访问协议)作为一种信息交互协议在分布式应用中非常广泛,如WebService.在使用.Net开发WebService时候, ...

  3. Web Service学习之八:Soap消息详解

    一.区别概念 WSDL是网络服务描述语言,是XML文档:它包含一系列描述某个web service的定义或者说是规则.尤其是定义了传输Sope消息的结构 Soap:简单对象访问协议,是交换数据的一种协 ...

  4. SOAP消息的传递

    上一篇说了SOAP消息的创建,那么创建好了的SOAP消息要怎么发送给服务端呢? public class SoapTest { private String wsdlUri = "http: ...

  5. SOAP消息创建

    看了SOAP消息分析之后,大家对soap消息应该有了一个初步的认识,那么怎样自己编写一个soap消息呢? 先来创建一个简单的soap消息: @Test public void test1(){ try ...

  6. JAX-WS创建和处理SOAP消息

    JAX-WS规范是一组XML web services的JAVA API,在 JAX-WS中,一个远程调用可以转换为一个基于XML的协议例如SOAP,在使用JAX-WS过程中,开发者不需要编写任何生成 ...

  7. 写入soap消息以及与soap消息通信

    1.些了解一下soap消息的结构以及通信方式如下图:

  8. Web Service进阶(二)如何用Apache TCPMon来截获SOAP消息

    注:以下是关于TCPMon的一些使用常识,如果不需要或是已经熟悉就不用往下看了. 在WebService服务器和客户机之间会传递SOAP消息,有时我们需要得到这些消息以便调试,而Apache的TCPM ...

  9. 如何在WCF中用TcpTrace工具查看发送和接收的SOAP消息

    WCF对消息加密(只对消息加密,不考虑Authorize)其实很简单,只要在server和client端的binding加入security mode为Message(还有Transport, Tra ...

随机推荐

  1. C# 移动无标题栏窗体的几种方法

    第一种,手工移动. 该方法根据鼠标位置实现窗体的移动.网上有很多相关的例子,这里不再多讲. 第二种,调用系统API原理:是当鼠标左键按下时,让系统认为是在标题栏按下的.这里我们用到了winapi里的W ...

  2. 【Java学习笔记之二十五】初步认知Java内部类

    可以将一个类的定义放在另一个类的定义内部,这就是内部类. 内部类是一个非常有用的特性但又比较难理解使用的特性(鄙人到现在都没有怎么使用过内部类,对内部类也只是略知一二). 第一次见面 内部类我们从外面 ...

  3. 菜鸟的Xamarin.Forms前行之路——按钮的按下抬起事件的监控(可扩展至其他事件)

    提问:监控按钮的点击事件,可以通过按钮的Click事件,或者Command绑定,那么如何监控按钮的按下与抬起,或者移动,长按,双击等事件? 解决方法:各个平台自定义渲染依赖注入. 共享项目PCL: 1 ...

  4. 错误Deprecated: mysql_connect(): The mysql extension is deprecated and will be removed in the future:

    今天写PHP代码,遇到了这个非常不友好的报错(Deprecated: mysql_connect(): The mysql extension is deprecated and will be re ...

  5. DRAM(MT48LC8M32B2)学习

    Micron公司,型号为MT48LC8M32B2的DRAM,其86PIN的 TSOP封装引脚定义 Micron公司,型号为MT48LC8M32B2的DRAM,其86PIN的 TSOP封装引脚定义如上图 ...

  6. flannel 的连通与隔离 - 每天5分钟玩转 Docker 容器技术(61)

    上一节我们在 flannel 网络中部署了容器,本节讨论 flannel 的连通和隔离特性. flannel 网络连通性 测试 bbox1 和 bbxo2 的连通性: bbox1 能够 ping 到位 ...

  7. 美国总统大选,黑客组织“匿名者”(Anonymous)也来凑热闹

    美国总统大选,黑客组织"匿名者"(Anonymous)也来凑热闹 黑客组织"匿名者"向美国总统共和党候选人唐纳德•特朗普宣战,发誓将从4月1日开始向其发动大规模 ...

  8. Atomic类和CAS

    说Atomic类之前,先聊一聊volatile. 对volatile的第一印象就是可见性.所谓可见性,就是一个线程对共享变量的修改,别的线程能够感知到. 但是对于原子性,volatile是不能保证的. ...

  9. 23个适合Java开发者的大数据工具和框架

    转自:https://www.yidianzixun.com/article/0Ff4gqZQ?s=9&appid=yidian&ver=3.8.4&utk=6n9c2z37 ...

  10. php 自己封装的一些函数

    手机归属地函数 function get_mobile_area($phone){ $sms = array('province'=>'', 'supplier'=>''); //初始化变 ...