最近在做一个webservice的项目,本人选用的是Apache CXF来实现,因为需要再项目中进行大文件的传输问题,在网上找了很多这方面的资料,都不甚理想,说的都不够明白,有的文章讲的传输小文件还可以,在传输大文件的时候就会报内存溢出异常,这个是麻烦的事情,本人在综合了各位前辈的经验,终于实现了大文件大的传输问题,采用的是mtom的机制进行附件传输,废话少说,下面就是cxf整合spring进行大文件传输的一个例子,当然了,至于jar包就自己到官网下载了,首先开发客户端代码:
第一步:开发接口
package cn.genomics.signtureServer.cxf;
import javax.jws.WebParam;
import javax.jws.WebService;
import cn.genomics.signtureServer.model.Resume;
@WebService
public interface IFileUpload {
String upload(@WebParam(name="resume") Resume resume);
}
@WebService和(@WebParam这两个注释是不可以少的哦。
类Resume包含传输文件的参数:文件名,文件类型,数据源(可以是Datahandler或是一个字节数组)我这用的是Datahandler,代码如下:
package cn.genomics.signtureServer.model; 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; @XmlRootElement(name="resume") @XmlAccessorType(XmlAccessType.FIELD) public class Resume { private String fileName; private String fileType; @XmlMimeType("application/octet-stream") private DataHandler fileData; public String getFileName() { return fileName; } public void setFileName(String fileName) { this.fileName = fileName; } public String getFileType() { return fileType; } public void setFileType(String fileType) { this.fileType = fileType; } public DataHandler getFileData() { return fileData; } public void setFileData(DataHandler fileData) { this.fileData = fileData; } }
@XmlMimeType("application/octet-stream")记住这个注释是必不可少的,说明这是一个二进制文件。
第二步:开发接口实现类:
package cn.genomics.signtureServer.cxf; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import javax.jws.WebService; import cn.genomics.signtureServer.model.Resume; @WebService(endpointInterface="cn.genomics.signtureServer.cxf.IFileUpload") public class IFileUploadImpl implements IFileUpload { @Override public String upload(Resume resume) { File outFilePath = new File("F:\\上传文件");//文件上传的路径,自己想上传到哪就到哪,自己决定 File outFile = new File(outFilePath.getAbsolutePath() + File.separator + resume.getFileName() + "." + resume.getFileType()); if(!outFilePath.exists()) { outFilePath.mkdir(); } byte[] buf = new byte[1024 * 512]; int read = 0; BufferedInputStream bis = null; BufferedOutputStream bos = null; try { bis = new BufferedInputStream(resume.getFileData().getInputStream()); bos = new BufferedOutputStream(new FileOutputStream(outFile)); while((read = bis.read(buf)) != -1) { bos.write(buf,0,read); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { try { if(bos != null) { bos.close(); } if(bis != null) { bis.close(); } }catch(IOException e) { e.printStackTrace(); } } return "文件上传成功"; } }
接下来就是配置文件的配置了,首先是web.xml的配置:
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>CXFServlet</servlet-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>CXFServlet</servlet-name> <url-pattern>/sealService/*</url-pattern> </servlet-mapping> </web-app>
下面是applicationContext.xml的配置:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:http-conf="http://cxf.apache.org/transports/http/configuration" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <aop:aspectj-autoproxy/> <context:component-scan base-package="cn.genomics.signtureServer"/> <context:annotation-config/> <import resource="classpath:META-INF/cxf/cxf.xml"/> <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/> <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/> <http-conf:destination name="*.http-destination"> <http-conf:server ReceiveTimeout="90000"/> </http-conf:destination> <bean id="upload" class="cn.genomics.signtureServer.cxf.IFileUploadImpl"/> <jaxws:endpoint id="fileUpload" implementor="#upload" address="/FileUpload" publish="true"> <jaxws:features> <bean class="org.apache.cxf.feature.LoggingFeature" /> </jaxws:features> <jaxws:properties > <entry key="mtom-enabled" value="true"/> </jaxws:properties> </jaxws:endpoint> </beans>
到这里服务器端就开发完毕,把项目部署到tomcat容器里,访问地址:(我的是80端口)http://localhost/testFileUpload/sealService/FileUpload?wsdl,如果能访问的到,就说明成功了。下面的任务就是要开发客户端了。
首先接口:
package cn.genomics.signtureserver.cxf; import javax.jws.WebMethod; import javax.jws.WebParam; import javax.jws.WebResult; import javax.jws.WebService; import javax.jws.soap.SOAPBinding; @WebService(name = "IFileUpload", targetNamespace = "http://cxf.signtureServer.genomics.cn/") @SOAPBinding(use = SOAPBinding.Use.LITERAL, parameterStyle = SOAPBinding.ParameterStyle.WRAPPED) public interface IFileUpload { @WebMethod(operationName = "upload", action = "") @WebResult(name = "return", targetNamespace = "") String upload(@WebParam(name="resume")Resume resume); }
Resume类跟服务器端一样
接下来配置文件applicationContext_client.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:context="http://www.springframework.org/schema/context" xmlns:http-conf="http://cxf.apache.org/transports/http/configuration" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <import resource="classpath:META-INF/cxf/cxf.xml"/> <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/> <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/> <http-conf:conduit name="*.http-conduit"> <http-conf:client ConnectionTimeout="30000" ReceiveTimeout="60000"/> </http-conf:conduit> <bean id="client" class="cn.genomics.signtureserver.cxf.IFileUpload" factory-bean="clientFactory" factory-method="create"/> <bean id="clientFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean"> <property name="serviceClass" value="cn.genomics.signtureserver.cxf.IFileUpload"/> <property name="address" value="http://localhost/testFileUpload/sealService/FileUpload?wsdl"/> <property name="properties"> <map><entry key="mtom-enabled" value="true"></entry></map> </property> </bean> </beans>
<map><entry key="mtom-enabled" value="true"></entry></map>这个绝对不能少。
现在可以测试了:
package cn.genomics.signtureserver.cxf; import javax.activation.DataHandler; import javax.activation.FileDataSource; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { ApplicationContext con = new ClassPathXmlApplicationContext("applicationContext_client.xml"); IFileUpload iu = con.getBean("client",IFileUpload.class); Resume re = new Resume(); re.setFileName("h1"); re.setFileType("zip"); re.setFileData(new DataHandler(new FileDataSource("D:\\华大基因\\testDemo\\t1\\h1.zip"))); iu.upload(re); } }