采取web service传输超大数据(1)

采用web service传输超大数据

  因为以前也没有做过相关的web service开发,对于Xfire也只是知道有这么一个框架。当然现在它已经变成apache基金会旗下的一个开源项目CXF。不过,现在依旧有很多公司还在用Xfire作web service 的开发,这说明它在业界一向是口碑不错的啊。 

  在学习一个框架时,我强烈建议将其自带的例子部置运行几次,这样对于理解以及搭建运行环境都有很大的帮助,也不容易出错。

  在这里,我主要讲解一下用Xfire开发文件上传下载的web service应用。对于文件的传输Xfire主要有两种方式。一种是将文件编码为字符串的样式进行传输,但文件大小有一定的限制且效率较低;另一种是基于MTOM协议以附件字节流的形式进行传输,基本满足现有的文件传输大小并且效率较高。 

  首先,我们先把开发环境搭建好。在myeclipse新建一个web应用程序,将Xfire所需jar包复制到lib目录下,并在src目录下按照META-INF/xfire/services.xml些目录结构新建一个services.xml文件,如下图

  344x562

  接下来就是真正的环境配置了,打开WebRoot/WEB-INF/web.xml进行如下配置,如图

  554x421

  至此,Xfire框架已经整合到我们的web应用程序中了,这样我们就可以开发我们的web service 应用了。 

  对于第一种小文件传输方式开发如下:

  1.首先我们先定义一个接口,因为我们暴露给客户端的就是这个接口,定义如下:

  554x156

  2.主要是定义文件上传与下载的两个方法,下面我们编写接口的实现类。

  

  1. package org.carrot.file1; 
  2. import java.io.ByteArrayInputStream; 
  3. import java.io.File; 
  4. import java.io.FileInputStream; 
  5. import java.io.FileNotFoundException; 
  6. import java.io.FileOutputStream; 
  7. import java.io.IOException; 
  8. import java.io.InputStream; 
  9. import org.codehaus.xfire.util.Base64; 
  10. public class File1Impl implements File1 
  11.     @Override 
  12.     public String downFile(String fileName) 
  13.     { 
  14.         File file = new File("F:/", fileName); 
  15.         System.out.println(file.length()); 
  16.         StringBuffer buffer = new StringBuffer(); 
  17.         InputStream in; 
  18.         try 
  19.         { 
  20.             in = new FileInputStream(file); 
  21.             byte[] buff = new byte[1024 * 1024]; 
  22.             int len = 0; 
  23.             while (-1 != (len = in.read(buff, 0, 1024))) 
  24.             { 
  25.                 buffer.append(Base64.encode(buff, 0, len)); 
  26.             } 
  27.             in.close(); 
  28.         } 
  29.         catch (FileNotFoundException e1) 
  30.         { 
  31.             e1.printStackTrace(); 
  32.         } 
  33.         catch (IOException e) 
  34.         { 
  35.             e.printStackTrace(); 
  36.         } 
  37.         String fileString = buffer.toString(); 
  38.         System.out.println(fileString.length()); 
  39.         System.out.println("running"); 
  40.         return fileString; 
  41.     } 
  42.     @Override 
  43.     public String uploadFile(String file, String fileName) 
  44.     { 
  45.         File loadFile = new File("F:/", fileName); 
  46.         InputStream in = new ByteArrayInputStream(Base64.decode(file)); 
  47.         byte[] buffer = new byte[1024 * 1024]; 
  48.         int len = -1; 
  49.         try 
  50.         { 
  51.             FileOutputStream out = new FileOutputStream(loadFile); 
  52.             while (-1 != (len = in.read(buffer, 0, buffer.length))) 
  53.             { 
  54.                 out.write(buffer, 0, len); 
  55.             } 
  56.             in.close(); 
  57.             out.close(); 
  58.         } 
  59.         catch (FileNotFoundException e) 
  60.         { 
  61.             e.printStackTrace(); 
  62.             return "file not found"; 
  63.         } 
  64.         catch (IOException e) 
  65.         { 
  66.             e.printStackTrace(); 
  67.             return "error"; 
  68.         } 
  69.         return "success"; 
  70.     } 

  3.接下来就是我们对外发布服务信息的配置了,打开services.xml文件进行如下配置

  554x152

  这里的name指发布的服务名,namespace指命名空间用于区别,serviceClass指发布的接口,implementationClass指实现类,具体还有很多元素可以当阅相关文档,这里只列出几个我们常用的。

  4.最后我们只要将这个应用部署到服务器上发布,这里我用的是Tomcat6.x进行部署,如下

  554x197

  5.这时我们就可以启动Tomcat服务器进行一下访问测试了,在浏览器中输入网址:http://localhost:8080/MyFile/services

  554x193

  6.点击进入wsdl就可以看到我们发布的服务信息了

  554x281

  7.这样我们的服务就发布成功了,接下来就是编写客户端进行服务的调用看是否成功。在这里客户端既可以是java web应用,也可以是java一般应用,为了jar包好导入以下皆采用java web应用作为客户端调用。客户端调用我们的服务也有三种方式:动态方式(反射)、代理方式、客户端桩方式。

  注意:这里的三种方式是在java的环境下笔者所知的开发方式,在其它语言环境下开发并不是很了解,只知道C#也是采用客户端桩方式。

  动态方式:客户端采用动态方式要加入Xfire相关jar包就能调用服务的方法,类似java反射

  为了简单,调用服务我都写在一个main方法中,如下

  

  1. package org.carrot.client2; 
  2. import java.io.File; 
  3. import java.io.FileInputStream; 
  4. import java.io.FileNotFoundException; 
  5. import java.io.FileOutputStream; 
  6. import java.io.IOException; 
  7. import java.io.InputStream; 
  8. import java.net.URL; 
  9. import org.codehaus.xfire.client.Client; 
  10. import org.codehaus.xfire.transport.http.HttpTransport; 
  11. import org.codehaus.xfire.util.Base64; 
  12. public class Client2 
  13.     public static void main(String[] args) 
  14.     { 
  15.         try 
  16.         { 
  17.             URL myURL = new URL( 
  18.                     "http://localhost:8080/MyFile/services/File1 wsdl"); 
  19.             Client client = new Client(myURL); 
  20.             // 文件下载 
  21.              Object[] result = client.invoke("downFile", new Object[] 
  22.              { "java6webservice.doc" }); 
  23.              String fileName = "java6webservice.doc";            
  24.              File file = new File(fileName);         
  25.              byte[] bytes = Base64.decode((String) result[0]); 
  26.              System.out.println(bytes.length);   
  27.              file.createNewFile();       
  28.              FileOutputStream out = new FileOutputStream(file); 
  29.              out.write(bytes); 
  30.              out.flush(); 
  31.              out.close(); 
  32.             // 文件上传 
  33. //          String fileName2 = "java6webservice.doc"; 
  34. //          File file2 = new File("E:/", fileName2); 
  35. //          System.out.println(file2.length()); 
  36. //          StringBuffer sb = new StringBuffer(); 
  37. //          InputStream is = new FileInputStream(file2); 
  38. //          byte[] buff = new byte[1024 * 1024]; 
  39. //          int len = -1; 
  40. //          while (-1 != (len = is.read(buff, 0, buff.length))) 
  41. //          { 
  42. //              sb.append(Base64.encode(buff, 0, len)); 
  43. //          } 
  44. //          is.close(); 
  45. //          String fileString = sb.toString(); 
  46. //          System.out.println(fileString.length()); 
  47. //          Object[] result = client.invoke("uploadFile", new Object[] 
  48. //          { fileString, fileName2}); 
  49. //          System.out.println(result[0]); 
  50.         } 
  51.         catch (FileNotFoundException e) 
  52.         { 
  53.             e.printStackTrace(); 
  54.         } 
  55.         catch (IOException e) 
  56.         { 
  57.             e.printStackTrace(); 
  58.         } 
  59.         catch (Exception e) 
  60.         { 
  61.             e.printStackTrace(); 
  62.         } 
  63.     } 

  代理方式:需要加入Xfire相关jar包,并且客户端必须提供与服务端一样的接口,即我们的服务暴露给客户端的接口,包名也最好与服务端的一样。服务调用如下

  

  1. package org.carrot.client3; 
  2. import java.io.ByteArrayInputStream; 
  3. import java.io.File; 
  4. import java.io.FileInputStream; 
  5. import java.io.FileNotFoundException; 
  6. import java.io.FileOutputStream; 
  7. import java.io.IOException; 
  8. import java.io.InputStream; 
  9. import java.net.MalformedURLException; 
  10. import org.codehaus.xfire.client.Client; 
  11. import org.codehaus.xfire.client.XFireProxyFactory; 
  12. import org.codehaus.xfire.service.Service; 
  13. import org.codehaus.xfire.service.binding.ObjectServiceFactory; 
  14. import org.codehaus.xfire.util.Base64; 
  15. public class Client3 
  16.     public static void main(String[] args) 
  17.     { 
  18.         Service serviceModel = new ObjectServiceFactory().create(File1.class, 
  19.                 "File1", ";, null); 
  20.         File1 service = null; 
  21.         try 
  22.         { 
  23.             service = (File1) new XFireProxyFactory().create(serviceModel, 
  24.                     "http://localhost:8080/MyFile/services/File1"); 
  25.         } 
  26.         catch (MalformedURLException e) 
  27.         { 
  28.             // TODO Auto-generated catch block 
  29.             e.printStackTrace(); 
  30.         } 
  31.         //文件下载 
  32. //      String fileName1 = "java6webservice.doc"; 
  33. //      File file1 = new File("E:/", fileName1); 
  34. //      InputStream in = new ByteArrayInputStream(Base64 
  35. //              .decode(service 
  36. //                      .downFile(fileName1))); 
  37. //      byte[] buffer =  new byte[1024*1024]; 
  38. //      try 
  39. //      { 
  40. //          int len1 = -1; 
  41. //          file1.createNewFile(); 
  42. //          FileOutputStream out = new FileOutputStream(file1); 
  43. //          while(-1 != (len1 = in.read(buffer, 0, buffer.length))) 
  44. //          { 
  45. //              out.write(buffer, 0 , len1); 
  46. //          } 
  47. //          out.flush(); 
  48. //          out.close(); 
  49. //      } 
  50. //      catch (FileNotFoundException e) 
  51. //      { 
  52. //          e.printStackTrace(); 
  53. //      } 
  54. //      catch (IOException e) 
  55. //      { 
  56. //          e.printStackTrace(); 
  57. //      } 
  58. //      System.out.println(file1.length()); 
  59.         //文件 上传 
  60.         String fileName2 = "java6webservice.doc"; 
  61.         File file2 = new File("E:/", fileName2); 
  62.         System.out.println(file2.length()); 
  63.         StringBuffer sb = new StringBuffer(); 
  64.         InputStream is; 
  65.         try 
  66.         { 
  67.             is = new FileInputStream(file2); 
  68.             byte[] buff = new byte[1024 * 1024]; 
  69.             int len = -1; 
  70.             while (-1 != (len = is.read(buff, 0, buff.length))) 
  71.             { 
  72.                 sb.append(Base64.encode(buff, 0, len)); 
  73.             } 
  74.             is.close(); 
  75.         } 
  76.         catch (FileNotFoundException e1) 
  77.         { 
  78.             e1.printStackTrace(); 
  79.         } 
  80.         catch (IOException e) 
  81.         { 
  82.             e.printStackTrace(); 
  83.         } 
  84.         String fileString = sb.toString(); 
  85.         System.out.println(fileString.length()); 
  86.         service.uploadFile(fileString, fileName2); 
  87.     } 

  客户端桩方式:也是最容易理解的一种方式,它通过工具自动生成客户端代码,在调用服务时就好像在本地方法一样,同样需要加入Xfire相关jar包的支持。

  自动生成工具有很多,myeclipse自带就有。这里我采用的是官方给出的例子,用Ant工具来进行生成。我们要在客户端根路径下新建一个build.xml文件,如图

  294x172

  打开build.xml文件,配置我们要生成的信息,如下

  

  1. < xml version="1.0" encoding="UTF-8" $amp;>amp;$nbsp;
  2. <project default="genfiles" basedir="."$amp;>amp;$nbsp;
  3.     <property name="lib" value="WebRoot/WEB-INF/lib" /$amp;>amp;$nbsp;
  4.     <path id="myclasspath"$amp;>amp;$nbsp;
  5.         <fileset dir="${lib}"$amp;>amp;$nbsp;
  6.             <include name="*.jar" /$amp;>amp;$nbsp;
  7.         </fileset$amp;>amp;$nbsp;
  8.         <pathelement location="${genfiles}" /$amp;>amp;$nbsp;
  9.     </path$amp;>amp;$nbsp;
  10.     <property name="code_path" value="src" /$amp;>amp;$nbsp;
  11.     <propertynamepropertyname="wsdl_path" value="http://localhost:8080/MyFile/services/File1 wsdl" /$amp;>amp;$nbsp;
  12.     <property name="code_package" value="org.carrot.client1" /$amp;>amp;$nbsp;
  13.     <target name="genfiles" description="Generate the files"$amp;>amp;$nbsp;
  14.         <taskdef name="wsgen" classname="org.codehaus.xfire.gen.WsGenTask" classpathref="myclasspath" /$amp;>amp;$nbsp;
  15.         <wsgen outputDirectory="${code_path}" wsdl="${wsdl_path}" package="${code_package}" binding="xmlbeans" overwrite="true" /$amp;>amp;$nbsp;
  16.     </target$amp;>amp;$nbsp;
  17. </project$amp;>amp;$nbsp;

  我们运行此文件就会在src目录下生成一堆称之为桩的文件,如下图

  286x259

  大家可以看到在包org.carrot.client1下生成了三个文件File1Client.java、File1Impl.java、File1PortType.java。这里的Client1.java是我接下来要讲的我写的调用服务的测试类。有了这几个文件我们与服务端打交道就轻松多了,不信你看

  

  1. package org.carrot.client1; 
  2. import java.io.ByteArrayInputStream; 
  3. import java.io.File; 
  4. import java.io.FileInputStream; 
  5. import java.io.FileNotFoundException; 
  6. import java.io.FileOutputStream; 
  7. import java.io.IOException; 
  8. import java.io.InputStream; 
  9. import org.codehaus.xfire.util.Base64; 
  10. public class Client1 
  11.     public static void main(String[] args) 
  12.     { 
  13.         File1Client client = new File1Client(); 
  14.         File1PortType service = client.getFile1HttpPort(); 
  15.         //文件下载 
  16. //      String fileName1 = "java6webservice.doc"; 
  17. //      File file1 = new File("E:/", fileName1); 
  18. //      InputStream in = new ByteArrayInputStream(Base64 
  19. //              .decode(service 
  20. //                      .downFile(fileName1))); 
  21. //      byte[] buffer =  new byte[1024*1024]; 
  22. //      try 
  23. //      { 
  24. //          int len1 = -1; 
  25. //          file1.createNewFile(); 
  26. //          FileOutputStream out = new FileOutputStream(file1); 
  27. //          while(-1 != (len1 = in.read(buffer, 0, buffer.length))) 
  28. //          { 
  29. //              out.write(buffer, 0 , len1); 
  30. //          } 
  31. //          out.flush(); 
  32. //          out.close(); 
  33. //      } 
  34. //      catch (FileNotFoundException e) 
  35. //      { 
  36. //          e.printStackTrace(); 
  37. //      } 
  38. //      catch (IOException e) 
  39. //      { 
  40. //          e.printStackTrace(); 
  41. //      } 
  42. //      System.out.println(file1.length()); 
  43.         //文件 上传 
  44.         String fileName2 = "java6webservice.doc"; 
  45.         File file2 = new File("E:/", fileName2); 
  46.         System.out.println(file2.length()); 
  47.         StringBuffer sb = new StringBuffer(); 
  48.         InputStream is; 
  49.         try 
  50.         { 
  51.             is = new FileInputStream(file2); 
  52.             byte[] buff = new byte[1024 * 1024]; 
  53.             int len = -1; 
  54.             while (-1 != (len = is.read(buff, 0, buff.length))) 
  55.             { 
  56.                 sb.append(Base64.encode(buff, 0, len)); 
  57.             } 
  58.             is.close(); 
  59.         } 
  60.         catch (FileNotFoundException e1) 
  61.         { 
  62.             e1.printStackTrace(); 
  63.         } 
  64.         catch (IOException e) 
  65.         { 
  66.             e.printStackTrace(); 
  67.         } 
  68.         String fileString = sb.toString(); 
  69.         System.out.println(fileString.length()); 
  70.         service.uploadFile(fileString, fileName2);   
  71.     } 

  上面的测试类调用服务,我们只写了两行代码就搞定了是不是比前面两种方式简单多了。经本人测试这三种方式都能够成功的运行。但是我们从代码上可以分析出,这三种方式的文件传输本质上都是一样的。就是将文件编码为字符串的形式再传出去,再深入一点也就是将文件整个读入内存中然后一并发出去。如果文件太大就会报内存溢出的问题,并且对于字符串编码的转换也是非常耗时的。所以这种方式只能传一些小文件,大文件就不行了。下面我就要讲的是Xfire支持的一种优化的支持大数据二进制流方式传输文件的技术MTOM,在Xfire自带的例子中已有很详细的介绍了。

  对于第二种大文件传输方式开发如下:

  注意:用MTOM时建议大家用java ee6的库,因数java ee5库中有个mail包冲突错误。

  1.第二种方式,主要针对大数据以二进制流进行文件的传输,主要支持byte[]、DataSource、DataHandler三种数据类型。这里我选用DataHandler进行讲解,同样我们要定义一个接口以及实现类,如下:

  接口:

  554x185

  实现类:

  

  1. package org.file.service; 
  2. import java.io.File; 
  3. import java.io.FileOutputStream; 
  4. import java.io.IOException; 
  5. import java.io.InputStream; 
  6. import javax.activation.DataHandler; 
  7. import javax.activation.FileDataSource; 
  8. public class MyFileImpl implements MyFile 
  9.     @Override 
  10.     public String uploadFile(DataHandler dh, String fileName) 
  11.     { 
  12.         long startTime = System.currentTimeMillis(); 
  13.         File file = new File("E://", fileName); 
  14.         try 
  15.         { 
  16.             file.createNewFile(); 
  17.             InputStream in = dh.getInputStream(); 
  18.             FileOutputStream out = new FileOutputStream(file); 
  19.             byte[] buff = new byte[1024 * 1024]; 
  20.             int len = -1; 
  21.             while (-1 != (len = in.read(buff, 0, buff.length))) 
  22.             { 
  23.                 out.write(buff, 0, len); 
  24.             } 
  25.             in.close(); 
  26.             out.flush(); 
  27.             out.close(); 
  28.         } 
  29.         catch (IOException e) 
  30.         { 
  31.             e.printStackTrace(); 
  32.             return "error"; 
  33.         } 
  34.         long endTime = System.currentTimeMillis(); 
  35.         System.out.println((endTime - startTime)/1000 + " s"); 
  36.         return "success"; 
  37.     } 
  38.     @Override 
  39.     public DataHandler downFile(String fileName) 
  40.     { 
  41.         File file = new File("F://", fileName); 
  42.         System.out.println(file.length()); 
  43.         DataHandler dh = new DataHandler(new FileDataSource(file)); 
  44.         return dh; 
  45.     } 

  2.基本的配置方式与第一种方式差不多,但是要用到MTOM技术,所以我们要在services.xml中增加一个元素,如下

  471x244

  3.接下来在Tomcat上部署发布都与方式一是一样的,这里就不多说了。

  4.好了这里重点讲的是如何开发客户端调用基于MTOM的应用。也许你会问是否也有三种方式,我想说官方的例子只给出了用代理方式,本人也经过大量测式另外两种方式都会出现一些莫名的问题。比如MTOM支持的数据类型,生成的客户端代码都会变成DataHandler类型。

  所以,我推荐大家还是用代理方式进行客户端的开发,客户端必须提供与服务端一样的接口(即我们的服务暴露给客户端的接口),包名也最好与服务端的一样,不然会出现问题。这里的客户端写法也与第一种方式有些差别,代码如下

  

  1. package org.file.service; 
  2. import java.io.File; 
  3. import java.io.FileOutputStream; 
  4. import java.io.IOException; 
  5. import java.io.InputStream; 
  6. import java.net.MalformedURLException; 
  7. import javax.activation.DataHandler; 
  8. import javax.activation.FileDataSource; 
  9. import org.codehaus.xfire.client.Client; 
  10. import org.codehaus.xfire.client.XFireProxyFactory; 
  11. import org.codehaus.xfire.service.Service; 
  12. import org.codehaus.xfire.service.binding.ObjectServiceFactory; 
  13. import org.codehaus.xfire.transport.http.HttpTransport; 
  14. public class MyTest 
  15.     public static void main(String[] args) throws MalformedURLException 
  16.     { 
  17.         Service serviceModel = new ObjectServiceFactory().create(MyFile.class, 
  18.                 "FileService", ";, null); 
  19.         MyFile service = (MyFile) new XFireProxyFactory().create(serviceModel, 
  20.                 "http://localhost:8080/MyFileService/services/FileService"); 
  21.         // 增加的代码,表示采用MTOM方式处理 
  22.         Client client = Client.getInstance(service); 
  23.         client.setProperty("mtom-enabled", "true"); 
  24.         client.setProperty(HttpTransport.CHUNKING_ENABLED, "true"); 
  25.         long startTime = System.currentTimeMillis(); 
  26.         //文件上传 
  27.         String fileName = "ZGC_CD_2011V4.1.iso"; 
  28.         File file = new File("F:/", fileName); 
  29.         DataHandler dh = new DataHandler(new FileDataSource(file)); 
  30.         System.out.println(service.uploadFile(dh, fileName)); 
  31.         //文件下载 
  32. //      File file1 = new File("E://", fileName); 
  33. // 
  34. //      DataHandler dh = service.downFile(fileName); 
  35. // 
  36. //      try 
  37. //      { 
  38. //          file1.createNewFile(); 
  39. //          InputStream in = dh.getInputStream(); 
  40. //          FileOutputStream out = new FileOutputStream(file1); 
  41. //          byte[] buff = new byte[1024 * 1024]; 
  42. //          int len = -1; 
  43. //          while (-1 != (len = in.read(buff, 0, buff.length))) 
  44. //          { 
  45. //              out.write(buff, 0, len); 
  46. //          } 
  47. //          in.close(); 
  48. //          out.flush(); 
  49. //          out.close(); 
  50. //          System.out.println("down over"); 
  51. //      } 
  52. //      catch (IOException e) 
  53. //      { 
  54. //          e.printStackTrace(); 
  55. //      } 
  56.         long endTime = System.currentTimeMillis(); 
  57.         System.out.println("time: " + (endTime - startTime) / 1000 + " s"); 
  58.     } 

  上面的代码与第一种方式写法大同小异,只是多了三行代码表示客户端采用MTOM方式处理数据类型。     

  

  1. Client client = Client.getInstance(service); 
  2. client.setProperty("mtom-enabled", "true"); 
  3. client.setProperty(HttpTransport.CHUNKING_ENABLED, "true"); 

  至此,客户端也就写完了,经测试1G的文件没有问题。

  希望对大家有帮助。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值