cxf学习笔记之传递附件
cxf是jws的实现,上传二进制文件主要借助MTOM来实现,只须在发布服务时进行简单的配置即可。
一、服务端
先建web工程
1、创建包括附件的复杂对象
package cn.ibeans.ws.pojo;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@XmlAccessorType(XmlAccessType.FIELD)public class Person {private String name;private String sex;@XmlMimeType("application/octet-stream")//注意,必不可少private DataHandler photo;/*public Person(String name, String sex) {super();this.name = name;this.sex = sex;}*/public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public DataHandler getPhoto() {return photo;}public void setPhoto(DataHandler photo) {this.photo = photo;}@Overridepublic String toString() {return "Person [name=" + name + ", sex=" + sex + "]";}}2、创建web服务接口
package cn.ibeans.ws;import java.util.List;import javax.jws.WebService;import cn.ibeans.ws.pojo.Person;/** * 设计一个人员报名的web服务,人员信息是一个复杂对象。 * 服务端接收该对象后进行必要的处理,并将报名结果回传客户端 * @author llf * */@WebServicepublic interface RegisterWebService {public String toRegister(Person person);public String toBatchRegister(List<Person> persons);}3、创建web服务接口的实现类
package cn.ibeans.ws.impl;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.util.List;import javax.activation.DataHandler;import javax.jws.WebService;import org.springframework.web.context.ContextLoader;import org.springframework.web.context.WebApplicationContext;import cn.ibeans.ws.RegisterWebService;import cn.ibeans.ws.pojo.Person;/** * @author llf * */@WebService(endpointInterface="cn.ibeans.ws.RegisterWebService")public class RegisterWebServiceImpl implements RegisterWebService {@Overridepublic String toRegister(Person person) {if(person!=null){System.out.print("注册信息是:"+person);//处理附件DataHandler data = person.getPhoto();try {//定义客户端上传的附件在服务器的存储路径和名称String path = this.getClass().getResource("/").getPath();//类路径(classes)在服务器上约绝对地址System.out.println(":"+path);WebApplicationContext ctx = ContextLoader.getCurrentWebApplicationContext();//获得web应用的上下文对象String root = ctx.getServletContext().getRealPath("/");//获得web应用在服务器的根路径的绝对地址root+="upload";File f = new File(root,person.getName()+".png");//进行流操作,将附件写到服务器硬盘InputStream is = data.getInputStream();OutputStream os = new FileOutputStream(f);byte[] bytes = new byte[1024];int len = 0;while((len=is.read(bytes))>0){os.write(bytes, 0, len);}is.close();os.close();} catch (IOException e) {e.printStackTrace();}}return person.getName();}@Overridepublic String toBatchRegister(List<Person> persons) {if(persons!=null){for(Person person:persons){System.out.println(person);}}return "ok";}}4、在spring中配置web服务
<?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:p="http://www.springframework.org/schema/p" 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://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" /> <jaxws:endpoint id="register" implementor="cn.ibeans.ws.impl.RegisterWebServiceImpl" address="/ws/register"> <jaxws:properties> <entry key="mtom-enabled" value="true"/><!--注意:传递附件的必须配置--> </jaxws:properties> </jaxws:endpoint> </beans>
4、发布web服务
启动web应用,并测试
二、客户端
1、创建web服务接口在客户端的副本和用来传递DTO对象
可以通过wsdl2java,如果有条件了可直接从服务端copy过来
package cn.ibeans.ws;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.XmlType;/** * <p>Java class for person complex type. * * */@XmlAccessorType(XmlAccessType.FIELD)//@XmlType(name = "person", propOrder = {"name", "sex"})public class Person { protected String name; protected String sex; @XmlMimeType("application/octet-stream")//注意,传递附件的必要配置 private DataHandler photo; public String getName() { return name; } public void setName(String value) { this.name = value; } public String getSex() { return sex; } public void setSex(String value) { this.sex = value; }public DataHandler getPhoto() {return photo;}public void setPhoto(DataHandler photo) {this.photo = photo;}}package cn.ibeans.ws;import java.util.List;import javax.jws.WebParam;import javax.jws.WebService;/** * This class was generated by Apache CXF 2.3.0 * Tue Jan 10 12:58:50 CST 2012 * Generated source version: 2.3.0 * */ @WebService(targetNamespace = "http://ws.ibeans.cn/", name = "RegisterWebService")//@XmlSeeAlso({ObjectFactory.class})public interface RegisterWebService { public java.lang.String toRegister(@WebParam(name = "arg0", targetNamespace = "") cn.ibeans.ws.Person arg0); public String toBatchRegister(List<Person> persons);}3、调用web服务,上传递附件
写一个JUnit类,测试一下:
/** * */package cn.ibeans.test.ws.client;import java.io.File;import java.util.HashMap;import java.util.List;import java.util.Map;import javax.activation.DataHandler;import javax.activation.DataSource;import javax.activation.FileDataSource;import junit.framework.Assert;import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;import org.junit.Before;import org.junit.Test;import cn.ibeans.ws.Person;import cn.ibeans.ws.RegisterWebService;/** * @author llf * */public class RegisterWSTest {private JaxWsProxyFactoryBean factory;private Person person;private List<Person> persons;@Beforepublic void setUp() throws Exception {factory = new JaxWsProxyFactoryBean();}@Testpublic void testRegister(){factory.setServiceClass(RegisterWebService.class);factory.setAddress("http://localhost:9090/cxfServer/ws/register");//以下三行设置客激活mtom功能,必不可少,Map<String,Object> map = new HashMap<String,Object>();map.put("mtom-enabled", true);factory.setProperties(map);RegisterWebService client = (RegisterWebService)factory.create();//若没有上面三行,此处创建不成功//以上语句的功能 可以通过spring来实现person = new Person();person.setName("zhangsan");person.setSex("man");DataSource ds = new FileDataSource(new File("D://wsdl.png"));//注意!person.setPhoto(new DataHandler(ds));//String result = client.toRegister(person);System.out.println("web service调用结果是:"+result);Assert.assertEquals("zhangsan", result);}}4、就是测试了,运行测试类,会发现服务调用成功。检查web工程下的upload目录,查看服务是否传递过来了。
三、注意事项
1、服务端和客户端的数据对象中,用来存储附件的属性都要用“@XmlMimeType("application/octet-stream")”进行注解,如下:
@XmlMimeType("application/octet-stream")private DataHandler photo;2、服务端和客户端的web服务配置都要声明mtom-enabled=true
服务端如果在spring中配置,如下:
<jaxws:endpoint id="register" implementor="cn.ibeans.ws.impl.RegisterWebServiceImpl" address="/ws/register"> <jaxws:properties> <entry key="mtom-enabled" value="true"/> </jaxws:properties></jaxws:endpoint>
客户端,如果用代码配置(也可用spring配置,类似服务端),如下:
Map<String,Object> map = new HashMap<String,Object>();map.put("mtom-enabled", true);factory.setProperties(map);