zoukankan      html  css  js  c++  java
  • JAVA6开发WebService (四)——SAAJ调用WebService

    转载自http://wuhongyu.iteye.com/blog/810571

       前面写了个JAX-WS的小例子,看到用JAVA6开发WebService确实很简单,也很方便,不过前面也说了,JAVA有三种WebService规范,JAX-WS是其中一种,现在来看看JAXM&SAAJ。

        最近在做一个接口平台的项目,接口嘛,当然得涉及到对WebService的接口了,我们计划做成一个通用的平台,通过配置文件进行配置后就可以动态对某一个接口进行调用,但像前面的例子那样,每次都要生成一堆客户端代码,这可受不了。如果调用的接口唯一,生成一次客户端代码当然没问题,但如果要调用的接口是动态的,这就不好办了。因此,我需要了解SOAP更多底层的细节,由我自己来组织SOAP中的内容而不是完全由代码生成器生成。

        仍使用前面例子中的服务器端:

    接口:

    package com.why.server;
    
    import javax.jws.WebParam;
    import javax.jws.WebService;
    import javax.jws.soap.SOAPBinding;
    import javax.xml.ws.soap.MTOM;
    
    /**
     * 
     * @author why
     *
     */
    @WebService(name="Hello")
    @SOAPBinding(style = SOAPBinding.Style.RPC)
    public interface Hello {
        public void printContext();
        public Customer selectCustomerByName(@WebParam(name = "c",header=true)Customer customer);
        public Customer selectMaxAgeCustomer(Customer c1, Customer c2);
    }

    实现类:

    package com.why.server;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Set;
    import javax.activation.DataHandler;
    import javax.activation.FileDataSource;
    import javax.annotation.Resource;
    import javax.jws.WebService;
    import javax.xml.ws.WebServiceContext;
    import javax.xml.ws.handler.MessageContext;
    import javax.xml.ws.soap.MTOM;
    
    /**
     * 
     * 通过@MTOM注解启动MTOM传输方式,使用CXF实现时,这个注解放在接口或者实现类上都可以,使用JDK1.6自带实现时,需标注在实现类上
     * @author why
     *
     */
    @WebService(serviceName="HelloService",portName="HelloServicePort",targetNamespace="http://service.why.com/",endpointInterface="com.why.server.Hello")
    @MTOM
    public class HelloImpl implements Hello {
        
        @Resource
        private WebServiceContext context;
        
        @Override
        public void printContext(){
            MessageContext ctx = context.getMessageContext();
            Set<String> set = ctx.keySet();
            for (String key : set) {
                System.out.println("{" + key + "," + ctx.get(key) +"}");
                try {
                    System.out.println("key.scope=" + ctx.getScope(key));
                } catch (Exception e) {
                    System.out.println(key + " is not exits");
                }
            }
        }
        
        @Override
        public Customer selectCustomerByName(Customer customer) {
            if("why".equals(customer.getName())){
                customer.setId(1);
                try {
                    customer.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse("1985-10-07"));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                customer.setImageData(new DataHandler(new FileDataSource(new File("c:"+ File.separator + "why.jpg"))));
            }else{
                customer.setId(2);
                customer.setBirthday(new Date());
                customer.setImageData(new DataHandler(new FileDataSource(new File("c:"+ File.separator + "origin.jpg"))));
            }
            return customer;
        }
        
        @Override
        public Customer selectMaxAgeCustomer(Customer c1, Customer c2) {
            try {
                // 输出接收到的附件
                System.out.println("c1.getImageData().getContentType()=" + c1.getImageData().getContentType());
                InputStream is = c1.getImageData().getInputStream();
                OutputStream os = new FileOutputStream("c:\temp1.jpg");
                byte[] bytes = new byte[1024];
                int c;
                while ((c = is.read(bytes)) != -1) {
                    os.write(bytes, 0, c);
                }
                os.close();
                
                System.out.println("c2.getImageData().getContentType()=" + c2.getImageData().getContentType());
                is = c2.getImageData().getInputStream();
                os = new FileOutputStream("c:\temp2.jpg");
                bytes = new byte[1024];
                while ((c = is.read(bytes)) != -1) {
                    os.write(bytes, 0, c);
                }
                os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            
            if (c1.getBirthday().getTime() > c2.getBirthday().getTime()){
                return c2;
            }
            else{
                return c1;
            }
        }
    }

    Customer类:

    package com.why.server;
    
    import java.util.Date;
    
    import javax.activation.DataHandler;
    import javax.xml.bind.annotation.XmlAccessType;
    import javax.xml.bind.annotation.XmlAccessorType;
    import javax.xml.bind.annotation.XmlMimeType;
    import javax.xml.bind.annotation.XmlRootElement;
    
    /**
     * 
     * @author why
     *
     */
    @XmlRootElement(name = "Customer")
    @XmlAccessorType(XmlAccessType.FIELD)
    public class Customer {
        private long id;
        private String name;
        private Date birthday;
        @XmlMimeType("application/octet-stream")
        private DataHandler imageData;
        
        public long getId() {
            return id;
        }
        public void setId(long id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public Date getBirthday() {
            return birthday;
        }
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
        public DataHandler getImageData() {
            return imageData;
        }
        public void setImageData(DataHandler imageData) {
            this.imageData = imageData;
        }
    }

    发布:

    package com.why.server;
    
    import javax.xml.ws.Endpoint;
    
    public class SoapServer {
        public static void main(String[] args) {
            Endpoint.publish("http://localhost:8080/helloService",new HelloImpl());
    
        }
    }

        这次不生成客户端类,而是通过自己组织SOAP消息,向服务器发送请求。首先,我们需要一个到WebService服务的连接(就像Connection之于JDBC),通过javax.xml.soap.SOAPConnectionFactory的createConnection()可以获得一个WebService连接。获得连接之后,我们就可以组织我们的SOAP消息了。通过javax.xml.soap.MessageFactory的createMessage()方法,获得一个javax.xml.soap.SOAPMessage,SOAPMessage就是我们SOAP消息的入口。我们知道,SOAP其实就是一个XML,有了SOAPMessage这个入口,剩下的就是对XML的组织和解析了。对于SOAP消息的各个部分,SOAPMessage都有对应的接口:

            // 获取SOAP连接工厂
            SOAPConnectionFactory factory = SOAPConnectionFactory.newInstance();
            // 从SOAP连接工厂创建SOAP连接对象
            SOAPConnection connection = factory.createConnection();
            // 获取消息工厂
            MessageFactory mFactory = MessageFactory.newInstance();
            // 从消息工厂创建SOAP消息对象
            SOAPMessage message = mFactory.createMessage();
            // 创建SOAPPart对象
            SOAPPart part = message.getSOAPPart();
            // 创建SOAP信封对象
            SOAPEnvelope envelope = part.getEnvelope();
            // 创建SOAPHeader对象
            SOAPHeader header = message.getSOAPHeader();
            // 创建SOAPBody对
            SOAPBody body = envelope.getBody();

        把我们需要传递的参数组织好,通过connection.call方法进行对WebService的调用,他仍然会给我们返回一个SOAPMessage对象,对应服务器端的三个函数,我分别写了对应的三个方法对其进行调用,以下是我的客户端类:

    package com.why.client;
    import java.io.ByteArrayOutputStream;
    import java.io.FileOutputStream;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.URL;
    import java.util.Iterator;
    import java.util.UUID;
    import javax.activation.DataHandler;
    import javax.activation.FileDataSource;
    import javax.xml.namespace.QName;
    import javax.xml.soap.AttachmentPart;
    import javax.xml.soap.MessageFactory;
    import javax.xml.soap.SOAPBody;
    import javax.xml.soap.SOAPBodyElement;
    import javax.xml.soap.SOAPConnection;
    import javax.xml.soap.SOAPConnectionFactory;
    import javax.xml.soap.SOAPElement;
    import javax.xml.soap.SOAPEnvelope;
    import javax.xml.soap.SOAPHeader;
    import javax.xml.soap.SOAPHeaderElement;
    import javax.xml.soap.SOAPMessage;
    import javax.xml.soap.SOAPPart;
    
    /**
     * 
     * @author why
     *
     */
    public class SoapClient {
        public static void main(String[] args) throws Exception{
            
            printContext();
            
            selectCustomerByName();
            
            selectMaxAgeCustomer();
        }
        
        /**
         * 调用一个无参函数
         * @throws Exception
         */
        public static void printContext() throws Exception{
            // 获取SOAP连接工厂
            SOAPConnectionFactory factory = SOAPConnectionFactory.newInstance();
            // 从SOAP连接工厂创建SOAP连接对象
            SOAPConnection connection = factory.createConnection();
            // 获取消息工厂
            MessageFactory mFactory = MessageFactory.newInstance();
            // 从消息工厂创建SOAP消息对象
            SOAPMessage message = mFactory.createMessage();
            // 创建SOAPPart对象
            SOAPPart part = message.getSOAPPart();
            // 创建SOAP信封对象
            SOAPEnvelope envelope = part.getEnvelope();
            // 创建SOAPHeader对象
            SOAPHeader header = message.getSOAPHeader();
            // 创建SOAPBody对象
            SOAPBody body = envelope.getBody();
            
            // 创建XML的根元素
            SOAPBodyElement bodyElementRoot = body.addBodyElement(new QName("http://server.why.com/", "printContext", "ns1"));
            
            // 访问Web服务地址
            SOAPMessage reMessage = connection.call(message, new URL("http://127.0.0.1:8080/helloService"));
            // 控制台输出返回的SOAP消息
            OutputStream os = System.out;
            reMessage.writeTo(os);
            
            connection.close();
        }
        
        /**
         * 调用一个在soap:HEADER中传递参数的函数
         * @throws Exception
         */
        public static void selectCustomerByName() throws Exception{
            // 获取SOAP连接工厂
            SOAPConnectionFactory factory = SOAPConnectionFactory.newInstance();
            // 从SOAP连接工厂创建SOAP连接对象
            SOAPConnection connection = factory.createConnection();
            // 获取消息工厂
            MessageFactory mFactory = MessageFactory.newInstance();
            // 从消息工厂创建SOAP消息对象
            SOAPMessage message = mFactory.createMessage();
            // 创建SOAPPart对象
            SOAPPart part = message.getSOAPPart();
            // 创建SOAP信封对象
            SOAPEnvelope envelope = part.getEnvelope();
            // 创建SOAPHeader对象
            SOAPHeader header = message.getSOAPHeader();
            // 创建SOAPBody对象
            SOAPBody body = envelope.getBody();
            
            // 创建XML的根元素
            SOAPHeaderElement headerElementRoot = header.addHeaderElement(new QName("http://server.why.com/", "c", "ns1"));
            SOAPBodyElement bodyElementRoot = body.addBodyElement(new QName("http://server.why.com/", "selectCustomerByName", "ns1"));
            headerElementRoot.addChildElement(new QName("name")).addTextNode("why");
            
            // 访问Web服务地址
            SOAPMessage reMessage = connection.call(message, new URL("http://127.0.0.1:8080/helloService"));
            // 控制台输出返回的SOAP消息
            OutputStream os = System.out;
            reMessage.writeTo(os);
            
            // 输出SOAP消息中的附件
            Iterator<AttachmentPart> it = reMessage.getAttachments();
            while (it.hasNext()) {
                InputStream ins = it.next().getDataHandler().getInputStream();
                byte[] b = new byte[ins.available()];
                OutputStream ous = new FileOutputStream("c:\aaa.jpg");
                while (ins.read(b) != -1) {
                    ous.write(b);
                }
                ous.close();
            }
            connection.close();
        }
        
        /**
         * 调用一个在soap:Body中传递参数的函数
         * @throws Exception
         */
        public static void selectMaxAgeCustomer() throws Exception{
            // 获取SOAP连接工厂
            SOAPConnectionFactory factory = SOAPConnectionFactory.newInstance();
            // 从SOAP连接工厂创建SOAP连接对象
            SOAPConnection connection = factory.createConnection();
            // 获取消息工厂
            MessageFactory mFactory = MessageFactory.newInstance();
            // 从消息工厂创建SOAP消息对象
            SOAPMessage message = mFactory.createMessage();
            // 创建SOAPPart对象
            SOAPPart part = message.getSOAPPart();
            // 创建SOAP信封对象
            SOAPEnvelope envelope = part.getEnvelope();
            // 创建SOAPHeader对象
            SOAPHeader header = message.getSOAPHeader();
            // 创建SOAPBody对象
            SOAPBody body = envelope.getBody();
    
            // 设置Content-Type
            MimeHeaders hd = message.getMimeHeaders(); 
            hd.setHeader("Content-Type", "application/xop+xml; charset=utf-8; type="text/xml"");
    
            // 创建XML的根元素
            SOAPBodyElement bodyElementRoot = body.addBodyElement(new QName("http://server.why.com/", "selectMaxAgeCustomer", "ns1"));
            
            // 创建Customer实例1
            SOAPElement elementC1 = bodyElementRoot.addChildElement(new QName("arg0"));
            elementC1.addChildElement(new QName("id")).addTextNode("1");
            elementC1.addChildElement(new QName("name")).addTextNode("A");
            elementC1.addChildElement(new QName("birthday")).addTextNode("1989-01-28T00:00:00.000+08:00");
            // 创建附件对象
            AttachmentPart attachment = message.createAttachmentPart(new DataHandler(new FileDataSource("c:\c1.jpg")));
            // 设置Content-ID
            attachment.setContentId("<" + UUID.randomUUID().toString() + ">");
            attachment.setMimeHeader("Content-Transfer-Encoding", "binary");
            message.addAttachmentPart(attachment);
            SOAPElement elementData = elementC1.addChildElement(new QName("imageData"));
            
            // 添加XOP支持
            elementData.addChildElement(
                    new QName("http://www.w3.org/2004/08/xop/include", "Include","xop"))
                    .addAttribute(new QName("href"),"cid:" + attachment.getContentId().replaceAll("<", "").replaceAll(">", ""));
            
            // 创建Customer实例2
            SOAPElement elementC2 = bodyElementRoot.addChildElement(new QName("arg1"));
            elementC2.addChildElement(new QName("id")).addTextNode("2");
            elementC2.addChildElement(new QName("name")).addTextNode("B");
            elementC2.addChildElement(new QName("birthday")).addTextNode("1990-01-28T00:00:00.000+08:00");
            AttachmentPart attachment2 = message.createAttachmentPart(new DataHandler(new FileDataSource("c:\c2.jpg")));
            attachment2.setContentId("<" + UUID.randomUUID().toString() + ">");
            message.addAttachmentPart(attachment2);
            SOAPElement elementData2 = elementC2.addChildElement(new QName("imageData"));
            
            elementData2.addChildElement(
                    new QName("http://www.w3.org/2004/08/xop/include", "Include","xop"))
                    .addAttribute(new QName("href"),"cid:" + attachment2.getContentId().replaceAll("<", "").replaceAll(">", ""));
            
            // 控制台输出发送的SOAP消息
            OutputStream os = new ByteArrayOutputStream();
            message.writeTo(os);
            String soapStr = os.toString();
            System.out.println("
    @@@@@@@@@@@@@@@@@@
    "+soapStr+"
    @@@@@@@@@@@@@@@@@@");
            
            // 访问Web服务地址
            SOAPMessage reMessage = connection.call(message, new URL("http://127.0.0.1:8080/helloService"));
            // 控制台输出返回的SOAP消息
            OutputStream baos = new ByteArrayOutputStream();
            reMessage.writeTo(baos);
            String soapStr2 = baos.toString();
            System.out.println("
    #############
    "+soapStr2+"
    ################");
            
    //        // 输出SOAP消息中的第一个子元素的元素名称
            System.out.println("
    <<<<<<<<<<<<<<<<<<<" + reMessage.getSOAPBody().getFirstChild().getLocalName());
            // 输出SOAP消息中的附件
            Iterator<AttachmentPart> it = reMessage.getAttachments();
            while (it.hasNext()) {
                InputStream ins = it.next().getDataHandler().getInputStream();
                byte[] b = new byte[ins.available()];
                OutputStream ous = new FileOutputStream("c:\bbb.jpg");
                while (ins.read(b) != -1) {
                    ous.write(b);
                }
                ous.close();
            }
            
            connection.close();
            
        }
    }

        使用SAAJ创建附件时,需设置Content-Type=application/xop+xml; charset=utf-8; type="text/xml",否则服务器端获取不到这个附件,查看发送给服务器端的SOAP消息可以看到,默认Content-Type被置为text/xml; charset=utf-8,因此,需在代码中加入: 

    MimeHeaders hd = message.getMimeHeaders(); hd.setHeader("Content-Type", "application/xop+xml; charset=utf-8; type="text/xml""); 

    SOAPMessage有一个writeTo(OutputStream os)方法,可以将整个SOAP消息的内容写入一个输出流中,我们可以截获这个输出流的内容进行分析或再次整理。

  • 相关阅读:
    [daily][dpdk] 内核模块(网卡驱动)无法卸载
    [development][tcp/ip][ids] 一个简单有参考价值的库 libnids
    [development][http][libhtp] suricata的http库--libhtp
    [skill][http] http管道化连接
    [skill][telnet] 用telnet获取一个网页
    [daily][grub2] grub2修改内核选项
    [knowledge] big data things
    [knowledge][dpdk] open data plane
    [daily] docker
    [knowledge] 停止等待协议
  • 原文地址:https://www.cnblogs.com/dhl-2013/p/3680425.html
Copyright © 2011-2022 走看看