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

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

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

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

接口:

Java代码 收藏代码
  1. package com.why.server;
  2. import javax.jws.WebParam;
  3. import javax.jws.WebService;
  4. import javax.jws.soap.SOAPBinding;
  5. import javax.xml.ws.soap.MTOM;
  6. /**
  7. *
  8. * @author why
  9. *
  10. */
  11. @WebService(name="Hello")
  12. @SOAPBinding(style = SOAPBinding.Style.RPC)
  13. public interface Hello {
  14. public void printContext();
  15. public Customer selectCustomerByName(@WebParam(name = "c",header=true)Customer customer);
  16. public Customer selectMaxAgeCustomer(Customer c1, Customer c2);
  17. }

实现类:

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

Customer类:

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

发布:

Java代码 收藏代码
  1. package com.why.server;
  2. import javax.xml.ws.Endpoint;
  3. /**
  4. *
  5. * @author why
  6. *
  7. */
  8. public class SoapServer {
  9. public static void main(String[] args) {
  10. Endpoint.publish("http://localhost:8080/helloService",new HelloImpl());
  11. }
  12. }

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

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

Java代码 收藏代码
  1. MimeHeaders hd = message.getMimeHeaders();
  2. hd.setHeader("Content-Type", "application/xop+xml; charset=utf-8; type=\"text/xml\"");

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

附件是我的工程(2010-11-15更新)


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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值