因为以前也没有做过相关的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文件,如下图

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

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

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

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

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. {
  12. @Override
  13. public String downFile(String fileName)
  14. {
  15. File file = new File("F:/", fileName);
  16. System.out.println(file.length());
  17. StringBuffer buffer = new StringBuffer();
  18. InputStream in;
  19. try
  20. {
  21. in = new FileInputStream(file);
  22. ];
  23. ;
  24. )))
  25. {
  26. , len));
  27. }
  28. in.close();
  29. }
  30. catch (FileNotFoundException e1)
  31. {
  32. e1.printStackTrace();
  33. }
  34. catch (IOException e)
  35. {
  36. e.printStackTrace();
  37. }
  38. String fileString = buffer.toString();
  39. System.out.println(fileString.length());
  40. System.out.println("running");
  41. return fileString;
  42. }
  43. @Override
  44. public String uploadFile(String file, String fileName)
  45. {
  46. File loadFile = new File("F:/", fileName);
  47. InputStream in = new ByteArrayInputStream(Base64.decode(file));
  48. ];
  49. ;
  50. try
  51. {
  52. FileOutputStream out = new FileOutputStream(loadFile);
  53. , buffer.length)))
  54. {
  55. , len);
  56. }
  57. in.close();
  58. out.close();
  59. }
  60. catch (FileNotFoundException e)
  61. {
  62. e.printStackTrace();
  63. return "file not found";
  64. }
  65. catch (IOException e)
  66. {
  67. e.printStackTrace();
  68. return "error";
  69. }
  70. return "success";
  71. }
  72. }

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

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

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

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

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

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. {
  14. public static void main(String[] args)
  15. {
  16. try
  17. {
  18. URL myURL = new URL(
  19. "http://localhost:8080/MyFile/services/File1?wsdl");
  20. Client client = new Client(myURL);
  21. // 文件下载
  22. Object[] result = client.invoke("downFile", new Object[]
  23. { "java6webservice.doc" });
  24. String fileName = "java6webservice.doc";
  25. File file = new File(fileName);
  26. ]);
  27. System.out.println(bytes.length);
  28. file.createNewFile();
  29. FileOutputStream out = new FileOutputStream(file);
  30. out.write(bytes);
  31. out.flush();
  32. out.close();
  33. // 文件上传
  34. //          String fileName2 = "java6webservice.doc";
  35. //          File file2 = new File("E:/", fileName2);
  36. //          System.out.println(file2.length());
  37. //          StringBuffer sb = new StringBuffer();
  38. //          InputStream is = new FileInputStream(file2);
  39. //          byte[] buff = new byte[1024 * 1024];
  40. //          int len = -1;
  41. //          while (-1 != (len = is.read(buff, 0, buff.length)))
  42. //          {
  43. //              sb.append(Base64.encode(buff, 0, len));
  44. //          }
  45. //          is.close();
  46. //          String fileString = sb.toString();
  47. //          System.out.println(fileString.length());
  48. //          Object[] result = client.invoke("uploadFile", new Object[]
  49. //          { fileString, fileName2});
  50. //          System.out.println(result[0]);
  51. }
  52. catch (FileNotFoundException e)
  53. {
  54. e.printStackTrace();
  55. }
  56. catch (IOException e)
  57. {
  58. e.printStackTrace();
  59. }
  60. catch (Exception e)
  61. {
  62. e.printStackTrace();
  63. }
  64. }
  65. }

代理方式:需要加入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. {
  17. public static void main(String[] args)
  18. {
  19. Service serviceModel = new ObjectServiceFactory().create(File1.class,
  20. "File1", "http://file1.carrot.org/File1", null);
  21. File1 service = null;
  22. try
  23. {
  24. service = (File1) new XFireProxyFactory().create(serviceModel,
  25. "http://localhost:8080/MyFile/services/File1");
  26. }
  27. catch (MalformedURLException e)
  28. {
  29. // TODO Auto-generated catch block
  30. e.printStackTrace();
  31. }
  32. //文件下载
  33. //      String fileName1 = "java6webservice.doc";
  34. //      File file1 = new File("E:/", fileName1);
  35. //      InputStream in = new ByteArrayInputStream(Base64
  36. //              .decode(service
  37. //                      .downFile(fileName1)));
  38. //      byte[] buffer =  new byte[1024*1024];
  39. //      try
  40. //      {
  41. //          int len1 = -1;
  42. //          file1.createNewFile();
  43. //          FileOutputStream out = new FileOutputStream(file1);
  44. //          while(-1 != (len1 = in.read(buffer, 0, buffer.length)))
  45. //          {
  46. //              out.write(buffer, 0 , len1);
  47. //          }
  48. //          out.flush();
  49. //          out.close();
  50. //      }
  51. //      catch (FileNotFoundException e)
  52. //      {
  53. //          e.printStackTrace();
  54. //      }
  55. //      catch (IOException e)
  56. //      {
  57. //          e.printStackTrace();
  58. //      }
  59. //      System.out.println(file1.length());
  60. //文件 上传
  61. String fileName2 = "java6webservice.doc";
  62. File file2 = new File("E:/", fileName2);
  63. System.out.println(file2.length());
  64. StringBuffer sb = new StringBuffer();
  65. InputStream is;
  66. try
  67. {
  68. is = new FileInputStream(file2);
  69. ];
  70. ;
  71. , buff.length)))
  72. {
  73. , len));
  74. }
  75. is.close();
  76. }
  77. catch (FileNotFoundException e1)
  78. {
  79. e1.printStackTrace();
  80. }
  81. catch (IOException e)
  82. {
  83. e.printStackTrace();
  84. }
  85. String fileString = sb.toString();
  86. System.out.println(fileString.length());
  87. service.uploadFile(fileString, fileName2);
  88. }
  89. }

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

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

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

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

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

大家可以看到在包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. {
  12. public static void main(String[] args)
  13. {
  14. File1Client client = new File1Client();
  15. File1PortType service = client.getFile1HttpPort();
  16. //文件下载
  17. //      String fileName1 = "java6webservice.doc";
  18. //      File file1 = new File("E:/", fileName1);
  19. //      InputStream in = new ByteArrayInputStream(Base64
  20. //              .decode(service
  21. //                      .downFile(fileName1)));
  22. //      byte[] buffer =  new byte[1024*1024];
  23. //      try
  24. //      {
  25. //          int len1 = -1;
  26. //          file1.createNewFile();
  27. //          FileOutputStream out = new FileOutputStream(file1);
  28. //          while(-1 != (len1 = in.read(buffer, 0, buffer.length)))
  29. //          {
  30. //              out.write(buffer, 0 , len1);
  31. //          }
  32. //          out.flush();
  33. //          out.close();
  34. //      }
  35. //      catch (FileNotFoundException e)
  36. //      {
  37. //          e.printStackTrace();
  38. //      }
  39. //      catch (IOException e)
  40. //      {
  41. //          e.printStackTrace();
  42. //      }
  43. //      System.out.println(file1.length());
  44. //文件 上传
  45. String fileName2 = "java6webservice.doc";
  46. File file2 = new File("E:/", fileName2);
  47. System.out.println(file2.length());
  48. StringBuffer sb = new StringBuffer();
  49. InputStream is;
  50. try
  51. {
  52. is = new FileInputStream(file2);
  53. ];
  54. ;
  55. , buff.length)))
  56. {
  57. , len));
  58. }
  59. is.close();
  60. }
  61. catch (FileNotFoundException e1)
  62. {
  63. e1.printStackTrace();
  64. }
  65. catch (IOException e)
  66. {
  67. e.printStackTrace();
  68. }
  69. String fileString = sb.toString();
  70. System.out.println(fileString.length());
  71. service.uploadFile(fileString, fileName2);
  72. }
  73. }

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

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

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

1.第二种方式,主要针对大数据以二进制流进行文件的传输,主要支持byte[]、DataSource、DataHandler三种数据类型。这里我选用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 javax.activation.DataHandler;
  7. import javax.activation.FileDataSource;
  8. public class MyFileImpl implements MyFile
  9. {
  10. @Override
  11. public String uploadFile(DataHandler dh, String fileName)
  12. {
  13. long startTime = System.currentTimeMillis();
  14. File file = new File("E://", fileName);
  15. try
  16. {
  17. file.createNewFile();
  18. InputStream in = dh.getInputStream();
  19. FileOutputStream out = new FileOutputStream(file);
  20. ];
  21. ;
  22. , buff.length)))
  23. {
  24. , len);
  25. }
  26. in.close();
  27. out.flush();
  28. out.close();
  29. }
  30. catch (IOException e)
  31. {
  32. e.printStackTrace();
  33. return "error";
  34. }
  35. long endTime = System.currentTimeMillis();
  36. + " s");
  37. return "success";
  38. }
  39. @Override
  40. public DataHandler downFile(String fileName)
  41. {
  42. File file = new File("F://", fileName);
  43. System.out.println(file.length());
  44. DataHandler dh = new DataHandler(new FileDataSource(file));
  45. return dh;
  46. }
  47. }

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

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

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

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

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

希望对大家有帮助。

采用web service传输超大数据的更多相关文章

  1. 使用Fiddler解析WCF RIA Service传输的数据

    原文 http://www.cnblogs.com/wintersun/archive/2011/01/05/1926386.html 使用Fiddler 2 解析WCF RIA Service传输的 ...

  2. iOS开发网络篇之Web Service和XML数据解析

    郝萌主倾心贡献,尊重作者的劳动成果,请勿转载. 假设文章对您有所帮助,欢迎给作者捐赠,支持郝萌主.捐赠数额任意,重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载:点我传送 游戏官方下 ...

  3. 通过Places API Web Service获取兴趣点数据

    实验将爬取新加坡地区的银行POI数据 数据库采用mongodb,请自行安装,同时申请google的key 直接上代码 #coding=utf-8 import urllib import json i ...

  4. asp.net项目下的web service返回json数据问题

    App_Code目录下放置WebService.cs文件,文件内容如: using System; using System.Collections.Generic; using System.Dat ...

  5. 构建安全的Xml Web Service系列之SSL篇

    原文:构建安全的Xml Web Service系列之SSL篇 首先介绍一下SSL, SSL 的英文全称是 "Secure Sockets Layer" ,中文名为 "安全 ...

  6. 几种通讯协议的比较RMI > Httpinvoker >= Hessian >> Burlap >> web service

    一.综述本文比较了RMI,Hessian,Burlap,Httpinvoker,web service等5种通讯协议的在不同的数据结构和不同数据量时的传输性能.RMI是java语言本身提供的远程通讯协 ...

  7. 转-Web Service中三种发送接受协议SOAP、http get、http post

    原文链接:web服务中三种发送接受协议SOAP/HTTP GET/HTTP POST 一.web服务中三种发送接受协议SOAP/HTTP GET/HTTP POST 在web服务中,有三种可供选择的发 ...

  8. 项目中使用WCF替换asmx Web service总结

    以前项目解决方案中,用http协议的asmx Web service作服务器数据访问入口,在SoapHeader中写入用户名和加盐密码进行身份认证. http asmx服务是明文传输,传输过程中数据很 ...

  9. 几种通讯协议的比较RMI > Httpinvoker >= Hessian >> Burlap >> web service (转)

    一.综述 本文比较了RMI,Hessian,Burlap,Httpinvoker,web service等5种通讯协议的在不同的数据结构和不同数据量时的传输性能.RMI是java语言本身提供的通讯协议 ...

随机推荐

  1. javax.persistence.EntityNotFoundException: Unable to find报错

    这类错id 可能是10,可能是27,也可能是其他数字 错误描述: javax.persistence.EntityNotFoundException: Unable to find 某个类 with ...

  2. bzoj 1131 简单树形dp

    思路:随便想想就能想出来啦把...  卡了我一个vector... #include<bits/stdc++.h> #define LL long long #define fi firs ...

  3. SQL join关键字

    如果一张表有很多个字段可能填入起来十分的困难复杂,不如把它拆分成两个表,然后查看的时候合并起来. 比如我要记录学生的姓名,班级,成绩,父母的电话号码,那么我们可以创建一个表1 储存学生的姓名班级成绩, ...

  4. 洛谷P2704 [NOI2001]炮兵阵地 [状压DP]

    题目传送门 炮兵阵地 题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图 ...

  5. Python的扩展接口[3] -> Matlab引擎 -> 使用 Python 调用 Matlab 程序

    Python - Matlab 目录 Python-Matlab 引擎 Python-Matlab 数组 Python-Matlab 基本操作 Python-Matlab 调用 m 文件 Matlab ...

  6. 为什么23种设计模式里面没有MVC?

    作者:lorio链接:https://www.zhihu.com/question/27738109/answer/100241918来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载 ...

  7. 【Leetcode】583. Delete Operation for Two Strings

    583. Delete Operation for Two Strings Given two words word1 and word2, find the minimum number of st ...

  8. BeautifulSoup解析库

    解析库 解析器 使用方法 优势 劣势 Python标准库 BeautifulSoup(html, 'html.parser') 速度适中,容错能力强 老版本python容错能力差 lxml HTML解 ...

  9. 二. 创建Series和DataFrame对象

    创建对象 创建Series对象 Series可以通过列表,标量值,字典,ndarray,其他函数来创建 a = pf.Series([1,2,3,4]) # 列表创建 b = pd.Series(25 ...

  10. FastReport.Net使用:[21]表格(Table)控件

    对表格控件的一些常用操作 合并单元格:选择需要合并的单元格(按住Shitf多选),然后在右键菜单中选择[合并单元格].         2.删除/插入行 鼠标移到在行头,当鼠标状态变为向右的箭头时点击 ...