欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JAVA开发WebService (四)——SAAJ调用WebService

程序员文章站 2024-01-02 17:37:28
...

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

 

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

 

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

接口:

Java代码   JAVA开发WebService (四)——SAAJ调用WebService
            
    
    博客分类: Webservie webservice 
  1. package com.why.server;  
  2.   
  3. import javax.jws.WebParam;  
  4. import javax.jws.WebService;  
  5. import javax.jws.soap.SOAPBinding;  
  6. import javax.xml.ws.soap.MTOM;  
  7.   
  8. /** 
  9.  *  
  10.  * @author why 
  11.  * 
  12.  */  
  13. @WebService(name="Hello")  
  14. @SOAPBinding(style = SOAPBinding.Style.RPC)  
  15. public interface Hello {  
  16.     public void printContext();  
  17.     public Customer selectCustomerByName(@WebParam(name = "c",header=true)Customer customer);  
  18.     public Customer selectMaxAgeCustomer(Customer c1, Customer c2);  
  19. }  

实现类:

Java代码   JAVA开发WebService (四)——SAAJ调用WebService
            
    
    博客分类: Webservie webservice 
  1. package com.why.server;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileOutputStream;  
  5. import java.io.IOException;  
  6. import java.io.InputStream;  
  7. import java.io.OutputStream;  
  8. import java.text.ParseException;  
  9. import java.text.SimpleDateFormat;  
  10. import java.util.Date;  
  11. import java.util.Set;  
  12. import javax.activation.DataHandler;  
  13. import javax.activation.FileDataSource;  
  14. import javax.annotation.Resource;  
  15. import javax.jws.WebService;  
  16. import javax.xml.ws.WebServiceContext;  
  17. import javax.xml.ws.handler.MessageContext;  
  18. import javax.xml.ws.soap.MTOM;  
  19.   
  20. /** 
  21.  *  
  22.  * 通过@MTOM注解启动MTOM传输方式,使用CXF实现时,这个注解放在接口或者实现类上都可以,使用JDK1.6自带实现时,需标注在实现类上 
  23.  * @author why 
  24.  * 
  25.  */  
  26. @WebService(serviceName="HelloService",portName="HelloServicePort",targetNamespace="http://service.why.com/",endpointInterface="com.why.server.Hello")  
  27. @MTOM  
  28. public class HelloImpl implements Hello {  
  29.       
  30.     @Resource  
  31.     private WebServiceContext context;  
  32.       
  33.     @Override  
  34.     public void printContext(){  
  35.         MessageContext ctx = context.getMessageContext();  
  36.         Set<String> set = ctx.keySet();  
  37.         for (String key : set) {  
  38.             System.out.println("{" + key + "," + ctx.get(key) +"}");  
  39.             try {  
  40.                 System.out.println("key.scope=" + ctx.getScope(key));  
  41.             } catch (Exception e) {  
  42.                 System.out.println(key + " is not exits");  
  43.             }  
  44.         }  
  45.     }  
  46.       
  47.     @Override  
  48.     public Customer selectCustomerByName(Customer customer) {  
  49.         if("why".equals(customer.getName())){  
  50.             customer.setId(1);  
  51.             try {  
  52.                 customer.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse("1985-10-07"));  
  53.             } catch (ParseException e) {  
  54.                 e.printStackTrace();  
  55.             }  
  56.             customer.setImageData(new DataHandler(new FileDataSource(new File("c:"+ File.separator + "why.jpg"))));  
  57.         }else{  
  58.             customer.setId(2);  
  59.             customer.setBirthday(new Date());  
  60.             customer.setImageData(new DataHandler(new FileDataSource(new File("c:"+ File.separator + "origin.jpg"))));  
  61.         }  
  62.         return customer;  
  63.     }  
  64.       
  65.     @Override  
  66.     public Customer selectMaxAgeCustomer(Customer c1, Customer c2) {  
  67.         try {  
  68.             // 输出接收到的附件  
  69.             System.out.println("c1.getImageData().getContentType()=" + c1.getImageData().getContentType());  
  70.             InputStream is = c1.getImageData().getInputStream();  
  71.             OutputStream os = new FileOutputStream("c:\\temp1.jpg");  
  72.             byte[] bytes = new byte[1024];  
  73.             int c;  
  74.             while ((c = is.read(bytes)) != -1) {  
  75.                 os.write(bytes, 0, c);  
  76.             }  
  77.             os.close();  
  78.               
  79.             System.out.println("c2.getImageData().getContentType()=" + c2.getImageData().getContentType());  
  80.             is = c2.getImageData().getInputStream();  
  81.             os = new FileOutputStream("c:\\temp2.jpg");  
  82.             bytes = new byte[1024];  
  83.             while ((c = is.read(bytes)) != -1) {  
  84.                 os.write(bytes, 0, c);  
  85.             }  
  86.             os.close();  
  87.         } catch (IOException e) {  
  88.             e.printStackTrace();  
  89.         }  
  90.           
  91.         if (c1.getBirthday().getTime() > c2.getBirthday().getTime()){  
  92.             return c2;  
  93.         }  
  94.         else{  
  95.             return c1;  
  96.         }  
  97.     }  
  98. }  

Customer类:

Java代码   JAVA开发WebService (四)——SAAJ调用WebService
            
    
    博客分类: Webservie webservice 
  1. package com.why.server;  
  2.   
  3. import java.util.Date;  
  4.   
  5. import javax.activation.DataHandler;  
  6. import javax.xml.bind.annotation.XmlAccessType;  
  7. import javax.xml.bind.annotation.XmlAccessorType;  
  8. import javax.xml.bind.annotation.XmlMimeType;  
  9. import javax.xml.bind.annotation.XmlRootElement;  
  10.   
  11. /** 
  12.  *  
  13.  * @author why 
  14.  * 
  15.  */  
  16. @XmlRootElement(name = "Customer")  
  17. @XmlAccessorType(XmlAccessType.FIELD)  
  18. public class Customer {  
  19.     private long id;  
  20.     private String name;  
  21.     private Date birthday;  
  22.     @XmlMimeType("application/octet-stream")  
  23.     private DataHandler imageData;  
  24.       
  25.     public long getId() {  
  26.         return id;  
  27.     }  
  28.     public void setId(long id) {  
  29.         this.id = id;  
  30.     }  
  31.     public String getName() {  
  32.         return name;  
  33.     }  
  34.     public void setName(String name) {  
  35.         this.name = name;  
  36.     }  
  37.     public Date getBirthday() {  
  38.         return birthday;  
  39.     }  
  40.     public void setBirthday(Date birthday) {  
  41.         this.birthday = birthday;  
  42.     }  
  43.     public DataHandler getImageData() {  
  44.         return imageData;  
  45.     }  
  46.     public void setImageData(DataHandler imageData) {  
  47.         this.imageData = imageData;  
  48.     }  
  49. }  

发布:

Java代码   JAVA开发WebService (四)——SAAJ调用WebService
            
    
    博客分类: Webservie webservice 
  1. package com.why.server;  
  2.   
  3. import javax.xml.ws.Endpoint;  
  4.   
  5. /** 
  6.  *  
  7.  * @author why 
  8.  * 
  9.  */  
  10. public class SoapServer {  
  11.     public static void main(String[] args) {  
  12.         Endpoint.publish("http://localhost:8080/helloService",new HelloImpl());  
  13.   
  14.     }  
  15. }  

 

    这次不生成客户端类,而是通过自己组织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都有对应的接口:

Java代码   JAVA开发WebService (四)——SAAJ调用WebService
            
    
    博客分类: Webservie webservice 
  1. // 获取SOAP连接工厂  
  2. SOAPConnectionFactory factory = SOAPConnectionFactory.newInstance();  
  3. // 从SOAP连接工厂创建SOAP连接对象  
  4. SOAPConnection connection = factory.createConnection();  
  5. // 获取消息工厂  
  6. MessageFactory mFactory = MessageFactory.newInstance();  
  7. // 从消息工厂创建SOAP消息对象  
  8. SOAPMessage message = mFactory.createMessage();  
  9. // 创建SOAPPart对象  
  10. SOAPPart part = message.getSOAPPart();  
  11. // 创建SOAP信封对象  
  12. SOAPEnvelope envelope = part.getEnvelope();  
  13. // 创建SOAPHeader对象  
  14. SOAPHeader header = message.getSOAPHeader();  
  15. // 创建SOAPBody对  
  16. SOAPBody body = envelope.getBody();  

 

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

 

Java代码   JAVA开发WebService (四)——SAAJ调用WebService
            
    
    博客分类: Webservie webservice 
  1. package com.why.client;  
  2. import java.io.ByteArrayOutputStream;  
  3. import java.io.FileOutputStream;  
  4. import java.io.InputStream;  
  5. import java.io.OutputStream;  
  6. import java.net.URL;  
  7. import java.util.Iterator;  
  8. import java.util.UUID;  
  9. import javax.activation.DataHandler;  
  10. import javax.activation.FileDataSource;  
  11. import javax.xml.namespace.QName;  
  12. import javax.xml.soap.AttachmentPart;  
  13. import javax.xml.soap.MessageFactory;  
  14. import javax.xml.soap.SOAPBody;  
  15. import javax.xml.soap.SOAPBodyElement;  
  16. import javax.xml.soap.SOAPConnection;  
  17. import javax.xml.soap.SOAPConnectionFactory;  
  18. import javax.xml.soap.SOAPElement;  
  19. import javax.xml.soap.SOAPEnvelope;  
  20. import javax.xml.soap.SOAPHeader;  
  21. import javax.xml.soap.SOAPHeaderElement;  
  22. import javax.xml.soap.SOAPMessage;  
  23. import javax.xml.soap.SOAPPart;  
  24.   
  25. /** 
  26.  *  
  27.  * @author why 
  28.  * 
  29.  */  
  30. public class SoapClient {  
  31.     public static void main(String[] args) throws Exception{  
  32.           
  33.         printContext();  
  34.           
  35.         selectCustomerByName();  
  36.           
  37.         selectMaxAgeCustomer();  
  38.     }  
  39.       
  40.     /** 
  41.      * 调用一个无参函数 
  42.      * @throws Exception 
  43.      */  
  44.     public static void printContext() throws Exception{  
  45.         // 获取SOAP连接工厂  
  46.         SOAPConnectionFactory factory = SOAPConnectionFactory.newInstance();  
  47.         // 从SOAP连接工厂创建SOAP连接对象  
  48.         SOAPConnection connection = factory.createConnection();  
  49.         // 获取消息工厂  
  50.         MessageFactory mFactory = MessageFactory.newInstance();  
  51.         // 从消息工厂创建SOAP消息对象  
  52.         SOAPMessage message = mFactory.createMessage();  
  53.         // 创建SOAPPart对象  
  54.         SOAPPart part = message.getSOAPPart();  
  55.         // 创建SOAP信封对象  
  56.         SOAPEnvelope envelope = part.getEnvelope();  
  57.         // 创建SOAPHeader对象  
  58.         SOAPHeader header = message.getSOAPHeader();  
  59.         // 创建SOAPBody对象  
  60.         SOAPBody body = envelope.getBody();  
  61.           
  62.         // 创建XML的根元素  
  63.         SOAPBodyElement bodyElementRoot = body.addBodyElement(new QName("http://server.why.com/""printContext""ns1"));  
  64.           
  65.         // 访问Web服务地址  
  66.         SOAPMessage reMessage = connection.call(message, new URL("http://127.0.0.1:8080/helloService"));  
  67.         // 控制台输出返回的SOAP消息  
  68.         OutputStream os = System.out;  
  69.         reMessage.writeTo(os);  
  70.           
  71.         connection.close();  
  72.     }  
  73.       
  74.     /** 
  75.      * 调用一个在soap:HEADER中传递参数的函数 
  76.      * @throws Exception 
  77.      */  
  78.     public static void selectCustomerByName() throws Exception{  
  79.         // 获取SOAP连接工厂  
  80.         SOAPConnectionFactory factory = SOAPConnectionFactory.newInstance();  
  81.         // 从SOAP连接工厂创建SOAP连接对象  
  82.         SOAPConnection connection = factory.createConnection();  
  83.         // 获取消息工厂  
  84.         MessageFactory mFactory = MessageFactory.newInstance();  
  85.         // 从消息工厂创建SOAP消息对象  
  86.         SOAPMessage message = mFactory.createMessage();  
  87.         // 创建SOAPPart对象  
  88.         SOAPPart part = message.getSOAPPart();  
  89.         // 创建SOAP信封对象  
  90.         SOAPEnvelope envelope = part.getEnvelope();  
  91.         // 创建SOAPHeader对象  
  92.         SOAPHeader header = message.getSOAPHeader();  
  93.         // 创建SOAPBody对象  
  94.         SOAPBody body = envelope.getBody();  
  95.           
  96.         // 创建XML的根元素  
  97.         SOAPHeaderElement headerElementRoot = header.addHeaderElement(new QName("http://server.why.com/""c""ns1"));  
  98.         SOAPBodyElement bodyElementRoot = body.addBodyElement(new QName("http://server.why.com/""selectCustomerByName""ns1"));  
  99.         headerElementRoot.addChildElement(new QName("name")).addTextNode("why");  
  100.           
  101.         // 访问Web服务地址  
  102.         SOAPMessage reMessage = connection.call(message, new URL("http://127.0.0.1:8080/helloService"));  
  103.         // 控制台输出返回的SOAP消息  
  104.         OutputStream os = System.out;  
  105.         reMessage.writeTo(os);  
  106.           
  107.         // 输出SOAP消息中的附件  
  108.         Iterator<AttachmentPart> it = reMessage.getAttachments();  
  109.         while (it.hasNext()) {  
  110.             InputStream ins = it.next().getDataHandler().getInputStream();  
  111.             byte[] b = new byte[ins.available()];  
  112.             OutputStream ous = new FileOutputStream("c:\\aaa.jpg");  
  113.             while (ins.read(b) != -1) {  
  114.                 ous.write(b);  
  115.             }  
  116.             ous.close();  
  117.         }  
  118.         connection.close();  
  119.     }  
  120.       
  121.     /** 
  122.      * 调用一个在soap:Body中传递参数的函数 
  123.      * @throws Exception 
  124.      */  
  125.     public static void selectMaxAgeCustomer() throws Exception{  
  126.         // 获取SOAP连接工厂  
  127.         SOAPConnectionFactory factory = SOAPConnectionFactory.newInstance();  
  128.         // 从SOAP连接工厂创建SOAP连接对象  
  129.         SOAPConnection connection = factory.createConnection();  
  130.         // 获取消息工厂  
  131.         MessageFactory mFactory = MessageFactory.newInstance();  
  132.         // 从消息工厂创建SOAP消息对象  
  133.         SOAPMessage message = mFactory.createMessage();  
  134.         // 创建SOAPPart对象  
  135.         SOAPPart part = message.getSOAPPart();  
  136.         // 创建SOAP信封对象  
  137.         SOAPEnvelope envelope = part.getEnvelope();  
  138.         // 创建SOAPHeader对象  
  139.         SOAPHeader header = message.getSOAPHeader();  
  140.         // 创建SOAPBody对象  
  141.         SOAPBody body = envelope.getBody();  
  142.   
  143.         // 设置Content-Type  
  144.         MimeHeaders hd = message.getMimeHeaders();   
  145.         hd.setHeader("Content-Type""application/xop+xml; charset=utf-8; type=\"text/xml\"");  
  146.   
  147.         // 创建XML的根元素  
  148.         SOAPBodyElement bodyElementRoot = body.addBodyElement(new QName("http://server.why.com/""selectMaxAgeCustomer""ns1"));  
  149.           
  150.         // 创建Customer实例1  
  151.         SOAPElement elementC1 = bodyElementRoot.addChildElement(new QName("arg0"));  
  152.         elementC1.addChildElement(new QName("id")).addTextNode("1");  
  153.         elementC1.addChildElement(new QName("name")).addTextNode("A");  
  154.         elementC1.addChildElement(new QName("birthday")).addTextNode("1989-01-28T00:00:00.000+08:00");  
  155.         // 创建附件对象  
  156.         AttachmentPart attachment = message.createAttachmentPart(new DataHandler(new FileDataSource("c:\\c1.jpg")));  
  157.         // 设置Content-ID  
  158.         attachment.setContentId("<" + UUID.randomUUID().toString() + ">");  
  159.         attachment.setMimeHeader("Content-Transfer-Encoding""binary");  
  160.         message.addAttachmentPart(attachment);  
  161.         SOAPElement elementData = elementC1.addChildElement(new QName("imageData"));  
  162.           
  163.         // 添加XOP支持  
  164.         elementData.addChildElement(  
  165.                 new QName("http://www.w3.org/2004/08/xop/include""Include","xop"))  
  166.                 .addAttribute(new QName("href"),"cid:" + attachment.getContentId().replaceAll("<""").replaceAll(">"""));  
  167.           
  168.         // 创建Customer实例2  
  169.         SOAPElement elementC2 = bodyElementRoot.addChildElement(new QName("arg1"));  
  170.         elementC2.addChildElement(new QName("id")).addTextNode("2");  
  171.         elementC2.addChildElement(new QName("name")).addTextNode("B");  
  172.         elementC2.addChildElement(new QName("birthday")).addTextNode("1990-01-28T00:00:00.000+08:00");  
  173.         AttachmentPart attachment2 = message.createAttachmentPart(new DataHandler(new FileDataSource("c:\\c2.jpg")));  
  174.         attachment2.setContentId("<" + UUID.randomUUID().toString() + ">");  
  175.         message.addAttachmentPart(attachment2);  
  176.         SOAPElement elementData2 = elementC2.addChildElement(new QName("imageData"));  
  177.           
  178.         elementData2.addChildElement(  
  179.                 new QName("http://www.w3.org/2004/08/xop/include""Include","xop"))  
  180.                 .addAttribute(new QName("href"),"cid:" + attachment2.getContentId().replaceAll("<""").replaceAll(">"""));  
  181.           
  182.         // 控制台输出发送的SOAP消息  
  183.         OutputStream os = new ByteArrayOutputStream();  
  184.         message.writeTo(os);  
  185.         String soapStr = os.toString();  
  186.         System.out.println("\n@@@@@@@@@@@@@@@@@@\n"+soapStr+"\n@@@@@@@@@@@@@@@@@@");  
  187.           
  188.         // 访问Web服务地址  
  189.         SOAPMessage reMessage = connection.call(message, new URL("http://127.0.0.1:8080/helloService"));  
  190.         // 控制台输出返回的SOAP消息  
  191.         OutputStream baos = new ByteArrayOutputStream();  
  192.         reMessage.writeTo(baos);  
  193.         String soapStr2 = baos.toString();  
  194.         System.out.println("\n#############\n"+soapStr2+"\n################");  
  195.           
  196. //      // 输出SOAP消息中的第一个子元素的元素名称  
  197.         System.out.println("\n<<<<<<<<<<<<<<<<<<<" + reMessage.getSOAPBody().getFirstChild().getLocalName());  
  198.         // 输出SOAP消息中的附件  
  199.         Iterator<AttachmentPart> it = reMessage.getAttachments();  
  200.         while (it.hasNext()) {  
  201.             InputStream ins = it.next().getDataHandler().getInputStream();  
  202.             byte[] b = new byte[ins.available()];  
  203.             OutputStream ous = new FileOutputStream("c:\\bbb.jpg");  
  204.             while (ins.read(b) != -1) {  
  205.                 ous.write(b);  
  206.             }  
  207.             ous.close();  
  208.         }  
  209.           
  210.         connection.close();  
  211.           
  212.     }  
  213. }  

 

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

Java代码   JAVA开发WebService (四)——SAAJ调用WebService
            
    
    博客分类: Webservie webservice 
  1. MimeHeaders hd = message.getMimeHeaders();   
  2. hd.setHeader("Content-Type""application/xop+xml; charset=utf-8; type=\"text/xml\"");  

 

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

相关标签: webservice

上一篇:

下一篇: