CXF进阶篇

1CXF简单的HelloWorld、复杂对象传递、图片上传(MTOM)

(软件版本CXF2.3.1JDK1.6.0_10

可以用wsimport –keep http://localhost:9000/cxf?wsdl 生成客户端

也可以用CXFwsdl2java命令生成客户端代码

使用Cxf必须创建一个服务接口(客户端使用)、这个接口的实现类(服务端处理客户端请求的相关业务)、服务端启动类(发布服务)和客户端启动类(访问服务)。

注:Exception in thread “main” java.lang.NoClassDefFoundError:

Com/sun/mail/util/LineInputStream

         原因:JavaEE版本和JavaMail的版本不一致。

解决方法:windowàpreferencesàjava,把版本改成一致就可以了。

1.1helloword

首先导入cxf的所有包。

HelloWorld为例,服务接口:

package com.test;

import javax.jws.WebService;

@WebService//必须注解WebService,让cxf知道这个接口是发布的WebService

publicinterface HelloWorld

{

   public String sayHi(Stringname);

}

服务实现类:

package com.test;

import javax.jws.WebService;

@WebService

publicclass HelloWorldImplimplements HelloWorld

{

   publicString sayHi(String name)

{

System.out.println("Hello " + name);

       return"Hello " + name;

    }

}

服务端启动类:

package com.server;

import org.apache.cxf.jaxws.JaxWsServerFactoryBean;

import com.test.HelloWorldImpl;

publicclass ServerStart

{

   protected ServerStart()throws Exception

{

        HelloWorldImpl helloWorld =new HelloWorldImpl();

        String address ="http://localhost:9000/cxf";

       /**

       *也可以使用注释的方式发布

       */

       //Endpoint.publish(address, helloWorld);

        //发布服务

        JaxWsServerFactoryBean server =new JaxWsServerFactoryBean();

        server.setServiceClass(helloWorld.getClass());

        server.setAddress(address);

        server.create();

    }

   

   publicstaticvoid main(String[] args)throws Exception

{

       new ServerStart();

    }

}

客户端启动类:

package com.client;

import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

import com.test.HelloWorld;

publicclass ClientStart

{

   publicstaticvoid main(String args[])throws Exception

{

       JaxWsProxyFactoryBean factory =newJaxWsProxyFactoryBean();

        factory.setAddress("http://localhost:9000/cxf");

        HelloWorld client = factory.create(HelloWorld.class);

//调用客户端方法并打印在控制台

System.out.println(client.sayHi("cxf"));

    }

}

1.2CXF复杂对象的传递

第一步:创建存储复杂对象的类(因为WebServices的复杂对象的传递,一定要借助第三方对象(即自定义对象)来实现)

  1. package com.ws.model;
  2. import java.util.ArrayList;
  3. import java.util.HashMap;
  4. public class Users {
  5. private ArrayList<UserInfo> userList;// 不要用List类型
  6. private HashMap<Integer, UserInfo> userMap;// 不要用Map类型
  7. private UserInfo[] userArray;
  8. // geter/seter 方法
  9. }
package com.ws.model;

import java.util.ArrayList;
import java.util.HashMap;

public class Users {
	private ArrayList<UserInfo> userList;  // 不要用List类型
	private HashMap<Integer, UserInfo> userMap; // 不要用Map类型
	private UserInfo[] userArray;
	// geter/seter 方法
}

第二步:创建WebServices的服务端接口和实现类

  1. package com.ws.services;
  2. import javax.jws.WebService;
  3. import com.ws.model.UserInfo;
  4. import com.ws.model.Users;
  5. @WebService
  6. public interface IUserServices {
  7. public Users getAllUsers();
  8. public Users getUsersMap();
  9. public Users getUsersArray();
  10. }
package com.ws.services;

import javax.jws.WebService;
import com.ws.model.UserInfo;
import com.ws.model.Users;

@WebService
public interface IUserServices {

	public Users getAllUsers();
	
	public Users getUsersMap();
	
	public Users getUsersArray();

}
  1. package com.ws.services.impl;
  2. import java.util.ArrayList;
  3. import java.util.HashMap;
  4. import javax.jws.WebService;
  5. import com.ws.model.UserInfo;
  6. import com.ws.model.Users;
  7. import com.ws.services.IUserServices;
  8. @WebService
  9. publicclass UserServicesImpl implements IUserServices {
  10. public Users getAllUsers() {
  11. ArrayList<UserInfo> list = new ArrayList<UserInfo>();
  12. list.add(new UserInfo("vicky",23));
  13. list.add(new UserInfo("ivy",26));
  14. list.add(new UserInfo("simon",26));
  15. list.add(new UserInfo("carol",29));
  16. Users users = new Users();
  17. users.setUserList(list);
  18. return users;
  19. }
  20. public Users getUsersMap() {
  21. HashMap<Integer, UserInfo> map =new HashMap<Integer, UserInfo>();
  22. map.put(23,new UserInfo("vicky",23));
  23. map.put(22,new UserInfo("caty",22));
  24. map.put(24,new UserInfo("leah",24));
  25. map.put(25,new UserInfo("kelly",25));
  26. map.put(27,new UserInfo("ivy",27));
  27. map.put(26,new UserInfo("simon",26));
  28. map.put(29,new UserInfo("carol",29));
  29. Users users = new Users();
  30. users.setUserMap(map);
  31. return users;
  32. }
  33. public Users getUsersArray() {
  34. UserInfo[] userInfo = new UserInfo[5];
  35. for(int i=0;i<5;i++){
  36. UserInfo info = new UserInfo();
  37. info.setUserAge(23+i);
  38. info.setUserName("Array"+(i+1));
  39. userInfo[i] = info;
  40. }
  41. Users users = new Users();
  42. users.setUserArray(userInfo);
  43. return users;
  44. }
  45. }
package com.ws.services.impl;

import java.util.ArrayList;
import java.util.HashMap;
import javax.jws.WebService;
import com.ws.model.UserInfo;
import com.ws.model.Users;
import com.ws.services.IUserServices;

@WebService
public class UserServicesImpl implements IUserServices {

	public Users getAllUsers() {
		ArrayList<UserInfo> list = new ArrayList<UserInfo>();
		list.add(new UserInfo("vicky",23));
		list.add(new UserInfo("ivy",26));
		list.add(new UserInfo("simon",26));
		list.add(new UserInfo("carol",29));
		Users users = new Users();
		users.setUserList(list);
		return users;
	}

	public Users getUsersMap() {
		HashMap<Integer, UserInfo> map = new HashMap<Integer, UserInfo>();
		map.put(23, new UserInfo("vicky",23));
		map.put(22, new UserInfo("caty",22));
		map.put(24, new UserInfo("leah",24));
		map.put(25, new UserInfo("kelly",25));
		map.put(27, new UserInfo("ivy",27));
		map.put(26, new UserInfo("simon",26));
		map.put(29, new UserInfo("carol",29));
		
		Users users = new Users();
		users.setUserMap(map);
		return users;
	}

	public Users getUsersArray() {
		UserInfo[] userInfo = new UserInfo[5];
		for(int i=0;i<5;i++){
			UserInfo info = new UserInfo();
			info.setUserAge(23+i);
			info.setUserName("Array"+(i+1));
			userInfo[i] = info;
		}
		Users users = new Users();
		users.setUserArray(userInfo);
		return users;
	}

}

第三步:创建WebServices的服务端

  1. package com.test;
  2. import javax.xml.ws.Endpoint;
  3. import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
  4. import com.ws.services.impl.UserServicesImpl;
  5. publicclass ServerTest {
  6. public ServerTest(){
  7. // 发布User服务接口
  8. Endpoint.publish("http://localhost:8090/userInfoServices",new UserServicesImpl());
  9. }
  10. public static void main(String[] args) {
  11. // 启动服务
  12. new ServerTest();
  13. System.out.println("Server ready...");
  14. try {
  15. Thread.sleep(1000*300);//休眠五分分钟,便于测试
  16. } catch (InterruptedException e) {
  17. e.printStackTrace();
  18. }
  19. System.out.println("Server exit...");
  20. System.exit(0);
  21. }
  22. }
package com.test;

import javax.xml.ws.Endpoint;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
import com.ws.services.impl.UserServicesImpl;

public class ServerTest {
	public ServerTest(){
		// 发布User服务接口
		Endpoint.publish("http://localhost:8090/userInfoServices", new UserServicesImpl());
	}
	public static void main(String[] args) {
		// 启动服务
		new ServerTest();
		System.out.println("Server ready...");   
		try {
			Thread.sleep(1000*300);//休眠五分分钟,便于测试 
		} catch (InterruptedException e) {
			e.printStackTrace();
		}   
		System.out.println("Server exit...");   
		System.exit(0);
	}
}

第四步:创建WebServices的客户端,并测试
1、将服务端创建的复杂对象的类和接口copy到客户工程中,且路径要与服务端一致;
2、新建测试类进行测试

  1. package com.ws.client;
  2. import java.util.List;
  3. import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
  4. import com.ws.model.UserInfo;
  5. import com.ws.model.Users;
  6. import com.ws.server.IUserServices;
  7. publicclass UserTest {
  8. public static void main(String[] args) {
  9. //创建WebService客户端代理工厂
  10. JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
  11. //注册WebService接口
  12. factory.setServiceClass(IUserServices.class);
  13. //设置WebService地址
  14. factory.setAddress("http://localhost:8090/userInfoServices");
  15. IUserServices userServices = (IUserServices)factory.create();
  16. System.out.println("invoke userinfo webservice...");
  17. // 测试Map
  18. // testMap(userServices);
  19. // 测试List
  20. // testList(userServices);
  21. // 测试Array
  22. // testArray(userServices);
  23. System.exit(0);
  24. }
  25. public static void testArray(IUserServices userServices){
  26. Users users = userServices.getUsersArray();
  27. if(users!=null){
  28. UserInfo[] array = users.getUserArray();
  29. for(UserInfo info:array){
  30. System.out.println("UserName: "+info.getUserName());
  31. System.out.println("UserAge : "+info.getUserAge());
  32. }
  33. }
  34. }
  35. publicstatic void testList(IUserServices userServices){
  36. Users users = userServices.getAllUsers();
  37. if(users!=null){
  38. List<UserInfo> list = users.getUserList();
  39. for(UserInfo info:list){
  40. System.out.println("UserName: "+info.getUserName());
  41. System.out.println("UserAge : "+info.getUserAge());
  42. }
  43. }
  44. }
  45. public static void testMap(IUserServices userServices){
  46. Users users = userServices.getUsersMap();
  47. if(users!=null){
  48. UserInfo info = users.getUserMap().get(23);
  49. System.out.println("UserName: "+info.getUserName());
  50. System.out.println("UserAge : "+info.getUserAge());
  51. }
  52. }
  53. }
package com.ws.client;

import java.util.List;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import com.ws.model.UserInfo;
import com.ws.model.Users;
import com.ws.server.IUserServices;

public class UserTest {
	public static void main(String[] args) {
		//创建WebService客户端代理工厂   
		JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();   
		//注册WebService接口   
		factory.setServiceClass(IUserServices.class);   
		//设置WebService地址   
		factory.setAddress("http://localhost:8090/userInfoServices");        
		IUserServices userServices = (IUserServices)factory.create();   
		System.out.println("invoke userinfo webservice...");
		// 测试Map
//		testMap(userServices);
		// 测试List
//		testList(userServices);
		// 测试Array
//		testArray(userServices);
		System.exit(0);   
	} 
	
	public static void testArray(IUserServices userServices){
		Users users = userServices.getUsersArray();
		if(users!=null){
			UserInfo[] array = users.getUserArray();
			for(UserInfo info:array){
				System.out.println("UserName: "+info.getUserName());
				System.out.println("UserAge : "+info.getUserAge());
			}
		}
	}
	
	public static void testList(IUserServices userServices){
		Users users = userServices.getAllUsers();
		if(users!=null){
			List<UserInfo> list = users.getUserList();
			for(UserInfo info:list){
				System.out.println("UserName: "+info.getUserName());
				System.out.println("UserAge : "+info.getUserAge());
			}
		}
	}
	
	public static void testMap(IUserServices userServices){
		Users users = userServices.getUsersMap();
		if(users!=null){
			UserInfo info = users.getUserMap().get(23);
			System.out.println("UserName: "+info.getUserName());
			System.out.println("UserAge : "+info.getUserAge());
		}
	}
}

第五步:运行服务端,验证webservices服务是否发布成功
第六步:运行客户端,验证是否成功调用webservices服务

注:在做webServices复杂对象传递时,返回值的类型不要用接口类型。例如(List 应该换成ArrayList ,Map应该换成HashMap)

1.3CXF图片上传(MTOM

附件上传需要借助MTOM,也需要一个实体类,用来处理上传的附件。

实体类:

publicclass Resume {

   private StringcandidateName;//附件名

   private StringresumeFileType;//附件类型

   private DataHandlerresume;//附件

   public String getCandidateName() {

       returncandidateName;

    }

   publicvoid setCandidateName(String candidateName) {

       this.candidateName = candidateName;

    }

   public String getResumeFileType() {

       returnresumeFileType;

    }

   publicvoid setResumeFileType(String resumeFileType) {

       this.resumeFileType = resumeFileType;

    }

   public DataHandler getResume() {

       returnresume;

    }

   publicvoid setResume(DataHandler resume) {

       this.resume = resume;

    }

}

服务接口:

@WebService

publicinterface ResumeUploadService {

   void uploadResume(@WebParam(name="resume") Resume resume);

}

接口实现类:

@WebService(endpointInterface ="com.webservice.ResumeUploadService",

         serviceName ="ResumeService")

publicclass ResumeUploadServiceImplimplements ResumeUploadService {

   publicvoid uploadResume(Resume resume) {

        DataHandler handler = resume.getResume();

       try{

            InputStream is = handler.getInputStream();

            OutputStream os =new FileOutputStream(

                   new File("d:\\" + resume.getCandidateName() + "."

                            + resume.getResumeFileType()));

           

           byte[] b =new byte[5*1000*1024];//设置附件最大限制

           int bytesRead = 0;

           while((bytesRead = is.read(b)) != -1){

                os.write(b, 0, bytesRead);

            }

            os.flush();

            os.close();

            is.close();

        }catch(IOException e){

            e.printStackTrace();

        }

    }

}

服务启动类:

publicclass ServerStart {

   publicstatic void main(String[] args)throws Exception{

       new ServerStart();

        System.out.println("Server ready...");

        Thread.sleep(5*60*1000);//5分钟后服务端退出

        System.out.println("Server exiting");

        System.exit(0);

    }

   

   protected ServerStart() {

        System.out.println("Starting Server...");

        ResumeUploadServiceImpl rus =new ResumeUploadServiceImpl();

        String address ="http://localhost:9000/mtom0.2/upload";

        Endpoint ep = Endpoint.publish(address, rus);

        Binding binding = ep.getBinding();

        ((SOAPBinding)binding).setMTOMEnabled(true);

    }

}

客户端启动类:

publicclass ClientStart {

   /**

    * @paramargs

    */

   publicstatic void main(String[] args)throws Exception{

        JaxWsProxyFactoryBean factory =new JaxWsProxyFactoryBean();

        factory.setServiceClass(ResumeUploadService.class);

        factory.setAddress("http://localhost:9000/mtom0.2/upload");

        ResumeUploadService client = (ResumeUploadService)factory.create();

        Resume resume =new Resume();

       

       int i =new Random().nextInt();

System.out.println("生成的随机数为:" + i);

        resume.setCandidateName("cxf" + i);//设置附件名

        resume.setResumeFileType("png");//设置附件类型

       

        DataSource source =new FileDataSource(new File("e:\\upload.png"));

        resume.setResume(new DataHandler(source));

       //测试文件大小

        InputStream is = resume.getResume().getInputStream();

        System.out.println("文件大小为:" + is.available());

       

        client.uploadResume(resume);//开始上传附件

System.out.println("上传成功!");

        System.exit(0);

    }

}

2CXFMTOM

(原文地址:http://blog.csdn.net/fhd001/archive/2010/08/05/5789311.aspx)

MTOM消息传输优化机制Message Transmission and Optimization Mechanism)是一个标准的服务,让你的服务传输二进制数据更方便,更有效率。很多框架都支持MTOM---Axis2,JAX-WS RI, JBoss WS , XFire , Microsoft WCF ,等更多.如果二进制是xml文档的一部分,它需要base64编码。当MTOM在一个服务上启用时,它可能需要二进制数据且通常是xml文档的一部分, 并为它创建一个附件。

启用MTOM是一个相当简单的过程。首先,你必须注解POJO类型或schema类型.........下面告诉你怎样为JAXB激活MTOM.   MTOM也支持Aegis.

1、   注解

a. 为MTOM修改你的schema

假如我们有这样一个Picture的schema类型,如:

<schema targetNamespace="http://pictures.com"

  xmlns:xsd="http://www.w3.org/2001/XMLSchema">

  <element name="Picture">

    <complexType>

      <sequence>

        <element name="Title" type="xsd:string"/>

        <element name="ImageData" type="xsd:base64Binary"/>

      </sequence>

    </complexType>

  </element>

</schema>

在这种情况下,ImageData元素是我们想作为附件传送。我们只需要添加一个xmime : expectedContentTypes注解:

<schema targetNamespace="http://pictures.com"

  xmlns:xsd="http://www.w3.org/2001/XMLSchema"

  xmlns:xmime="http://www.w3.org/2005/05/xmlmime">

  <element name="Picture">

    <complexType>

      <sequence>

        <element name="Title" type="xsd:string"/>

        <element name="ImageData" type="xsd:base64Binary"

           xmime:expectedContentTypes="application/octet-stream"/>

      </sequence>

    </complexType>

  </element>

</schema>

这告诉JAXB(其中WSDL2Java用来为你的服务生成POJO),这个字段可以是任何内容类型。而不是为base64Binary创建一个byte[]数组.它将创建一个DataHandler ,而不是用于流数据。

b. 注解你的JAXB bean来启用MTOM

@XmlType

public class Picture {

  private String title;

  @XmlMimeType("application/octet-stream")

  private DataHandler imageData;

  public String getTitle() { return title; }

  public void setTitle(String title) { this.title = title; }

  public DataHandler getImageData() { return imageData; }

  public void setImageData(DataHandler imageData) { this.imageData = imageData; }

}

2、   在你的服务上启用MTOM

如果你使用JAX-WS  API发布你的服务,你可以像这样启用MTOM,如:

import javax.xml.ws.Endpoint;

import javax.xml.ws.soap.SOAPBinding;

Endpoint ep = Endpoint.publish("http://localhost/myService", new MyService());

SOAPBinding binding = (SOAPBinding) ep.getBinding();

binding.setMTOMEnabled(true);

或者,你用xml来发布你的服务:

<beans xmlns="http://www.springframework.org/schema/beans"

         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

         xmlns:jaxws="http://cxf.apache.org/jaxws"

         xsi:schemaLocation="

http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd

http://cxf.apache.org/jaxws http://cxf.apache.org/schema/jaxws.xsd">

  <jaxws:endpoint

    id="helloWorld"

    implementor="demo.spring.HelloWorldImpl"

    address="http://localhost/HelloWorld">

    <jaxws:properties>

      <entry key="mtom-enabled" value="true"/>

    </jaxws:properties>

  </jaxws:endpoint>

</beans>

如果你使用simple frontend,你可以在ServerFactoryBeanClientProxyFactoryBean设置mtom-enabled属性.

Map<String,Object> props = new HashMap<String, Object>();

props.put("mtom-enabled", Boolean.TRUE); // Boolean.TRUE or "true" will work as the property value here

ClientProxyFactoryBean pf = new ClientProxyFactoryBean();

pf.setPropertyies(props);

....

YourClient client = (YourClient) pf.create();

ServerFactoryBean sf = new ServerFactoryBean();

sf.setPropertyies(props);

...

sf.create();

你也可以用xml来配置(simple frontend):

<beans xmlns="http://www.springframework.org/schema/beans"

         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

         xmlns:simple="http://cxf.apache.org/simple"

         xsi:schemaLocation="

http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd

http://cxf.apache.org/simple http://cxf.apache.org/schema/simple.xsd">

  <simple:server

    id="helloWorld"

    serviceClass="demo.spring.HelloWorldImpl"

    address="http://localhost/HelloWorld">

    <simple:properties>

      <entry key="mtom-enabled" value="true"/>

    </simple:properties>

  </simple:server>

  <simple:client

    id="helloWorldClient"

    serviceClass="demo.spring.HelloWorldImpl"

    address="http://localhost/HelloWorld">

    <simple:properties>

      <entry key="mtom-enabled" value="true"/>

    </simple:properties>

  </simple:client>

</beans>

3、   使用DataHandlers

Picture picture = ...;

DataHandler handler = picture.getImageData();

InputStream is = handler.getInputStream();

DataSource source = new ByteArrayDataSource(new byte[] {...}, "content/type");

DataSource source = new FileDataSource(new File("my/file"));

Picture picture = new Picture();

picture.setImageData(new DataHandler(source));

4、   大文件上传

上传需要一个实体类(类上需注解XmlAccessorType(XmlAccessType.FIElD)),实例类里有三个参数(candidateName附件名、resumeFileType附件类型、DataHandler resume附件DataHandler上需注解@XmlMineType(“application/octet-stream”)还需要在服务接口注解@SOAPBinding(style=”SOAPBinding.Style.RPC”)@MTOM来开启MTOM

@SOAPBinding(style = SOAPBinding.Style.RPC)指定SOAP消息样式,有两个枚举值:SOAPBinding.Style.DOCUMENT(默认)和 SOAPBinding.Style.RPC,可以对比这两种方式生成的wsdl会有所不同,而且生成的客户端代码也会有所不同。

附件实体类:

package com.pojo;

import javax.activation.DataHandler;

import javax.xml.bind.annotation.XmlAccessType;

import javax.xml.bind.annotation.XmlAccessorType;

import javax.xml.bind.annotation.XmlMimeType;

@XmlAccessorType(XmlAccessType.FIELD)

publicclass Resume {

   private StringcandidateName;//附件名

   private StringresumeFileType;//附件类型

   @XmlMimeType("application/octet-stream")

   private DataHandlerresume;//附件

   public String getCandidateName() {

       returncandidateName;

    }

   publicvoid setCandidateName(String candidateName) {

       this.candidateName = candidateName;

    }

   public String getResumeFileType() {

       returnresumeFileType;

    }

   publicvoid setResumeFileType(String resumeFileType) {

       this.resumeFileType = resumeFileType;

    }

   public DataHandler getResume() {

       returnresume;

    }

   publicvoid setResume(DataHandler resume) {

       this.resume = resume;

    }

}

接口类:

package com.webservice;

import java.io.IOException;

import javax.jws.WebParam;

import javax.jws.WebService;

import javax.jws.soap.SOAPBinding;

importjavax.xml.ws.soap.MTOM;

import com.pojo.Resume;

@WebService

@SOAPBinding(style=SOAPBinding.Style.RPC)

@MTOM

publicinterface ResumeUploadService {

   void uploadResume(@WebParam(name="resume") Resume resume) throws IOException;

}

接口实现类:

package com.webservice;

import java.io.File;

importjava.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import javax.activation.DataHandler;

import javax.jws.WebService;

import com.pojo.Resume;

@WebService(endpointInterface ="com.webservice.ResumeUploadService",

         serviceName ="ResumeService")

//@BindingType(SOAPBinding.SOAP11HTTP_MTOM_BINDING)

publicclass ResumeUploadServiceImplimplements ResumeUploadService {

   publicvoid uploadResume(Resume resume)throws IOException{

        DataHandler handler = resume.getResume();

       finalint BUFFER_SIZE = 50*1024*1024;//缓冲区大小为3M

       long fileLength = 0;

       int read = 0;

        InputStream is =null;

        OutputStream os =null;

       

       try{

//1.

            is = handler.getInputStream();

            os =new FileOutputStream(

                   new File("d:\\" + resume.getCandidateName() + "."

                            + resume.getResumeFileType()));

//          is = new BufferedInputStream(handler.getInputStream());

//          os = new BufferedOutputStream(new FileOutputStream("d:\\" + resume.getCandidateName() + "."

//                  + resume.getResumeFileType()));

            fileLength = is.available();

System.out.println("服务端测试文件大小:" + fileLength);

           byte[] b =new byte[BUFFER_SIZE];

           while((read = is.read(b)) != -1){

                os.write(b, 0, read);

               

            }

           

//2.目前测试6M文件可以上传,10M内存溢出

//

//          byte[] dst = new byte[BUFFER_SIZE];//每次读出3M

//          for(int offset=0; offset<fileLength; offset+=BUFFER_SIZE){

//              if(fileLength - offset >= BUFFER_SIZE){

//                  read = is.read(dst);

//                  os.write(dst, 0, read);

//System.out.println("test if run " + offset);

//              }else{

//                  read = is.read(dst);

//                  os.write(dst, 0, read);

//System.out.println("test else run");

//              }

//              read=0;

//              os.flush();

//          }

           

        }catch(IOException e){

            e.printStackTrace();

        }finally{

           if(is !=null)is.close();

           if(os !=null){

                os.flush();

                os.close();

            }

        }

    }

}

服务端启动类:

package com.server;

import javax.xml.ws.Endpoint;

publicclass ServerStart {

   /**

    * @paramargs

    * 上传附件的时候应注意把MyException自带的JavaEE 5 Libraries删掉,

    * 否则会出现Exceptionin thread "main"java.lang.NoClassDefFoundError:com/sun/mail/util/LineInputStream

    * 原因:JavaEE版本和JavaMail的版本不一致。

    */

   publicstatic void main(String[] args)throws Exception{

       new ServerStart();

        System.out.println("Server ready...");

        Thread.sleep(5*60*1000);//5分钟后服务端退出

        System.out.println("Server exiting");

        System.exit(0);

   }

   

   protected ServerStart() {

        System.out.println("Starting Server...");

        ResumeUploadServiceImpl rus =new ResumeUploadServiceImpl();

        String address ="http://localhost:9000/mtom0.2/upload";

        Endpoint.publish(address, rus);

//      Endpoint ep = Endpoint.publish(address, rus);

//      Binding binding = ep.getBinding();

//      System.out.println(binding.getBindingID());

//      ((SOAPBinding)binding).setMTOMEnabled(true);

    }

}

客户端启动类:

package com.client;

import java.io.File;

import java.io.InputStream;

import java.util.Random;

import javax.activation.DataHandler;

import javax.activation.DataSource;

import javax.activation.FileDataSource;

import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

import com.pojo.Resume;

import com.webservice.ResumeUploadService;

publicclass ClientStart {

   /**

    * @paramargs

    */

   publicstatic void main(String[] args)throws Exception{

        JaxWsProxyFactoryBean factory =new JaxWsProxyFactoryBean();

        factory.setServiceClass(ResumeUploadService.class);

        factory.setAddress("http://localhost:9000/mtom0.2/upload");

        ResumeUploadService client = (ResumeUploadService)factory.create();

        Resume resume =new Resume();

       

       //启动MTOM(有问题)

//      QName qname = new QName("http://webservice.com/", "ResumeService");

//      Service svc = Service.create(qname);

//      ResumeUploadService proxy = svc.getPort(ResumeUploadService.class);

//      BindingProvider bp = (BindingProvider) proxy;

//      SOAPBinding binding = (SOAPBinding) bp.getBinding();

//      binding.setMTOMEnabled(true);

       

       int i =new Random().nextInt();

System.out.println("生成的随机数为:" + i);

        resume.setCandidateName("cxf" + i);//设置附件名

       

        DataSource source =new FileDataSource(new File("e:\\myTools\\jdk-1_5_0-windows-i586.exe"));

        DataHandler handler =new DataHandler(source);

        resume.setResume(handler);//设置附件

       //得到附件类型

        StringfileType = source.getName().substring(source.getName().lastIndexOf(".")+1);

System.out.println("文件类型为:" + fileType);

        resume.setResumeFileType(fileType);//设置附件类型

       //测试文件大小

        InputStream is = resume.getResume().getInputStream();

        System.out.println("文件大小为:" + is.available() + "个字节");

       

        client.uploadResume(resume);//开始上传附件

System.out.println("上传成功!");

        System.exit(0);

    }

}

3、 CXFWS-Security安全机制

一个WebService挂在互联网上,如果知道地址,那么任何人都可以访问,所以应该考虑 WebService的安全问题。应该只让指定的客户端访问。下面利用Jax-WS的拦截器来做用户验证。

和上面例子一样,首先需要一个服务接口和服务实现类,这里省略。

其次需要2个身份验证的CallbackHandler

服务端CallbackHandler

package com.mms.webservice.test;

import java.io.IOException;

import javax.security.auth.callback.Callback;

import javax.security.auth.callback.CallbackHandler;

import javax.security.auth.callback.UnsupportedCallbackException;

import org.apache.ws.security.WSPasswordCallback;

publicclass ServerPasswordCallbackimplements CallbackHandler {

   publicvoid handle(Callback[] callbacks)throws IOException,

            UnsupportedCallbackException {

        WSPasswordCallback pwcb = (WSPasswordCallback) callbacks[0];

        String id = pwcb.getIdentifier();

       switch (pwcb.getUsage()) {

       case WSPasswordCallback.USERNAME_TOKEN_UNKNOWN:

           // 密码方式 plaintext

           if (!"cxf".equals(id)) {

               thrownew UnsupportedCallbackException(pwcb,

                       "username is invalid.");

            }

           if (!"mima".equals(pwcb.getPassword())) {

               thrownew UnsupportedCallbackException(pwcb,

                       "password is invalid.");

            }

           break;

       case WSPasswordCallback.DECRYPT:

       case WSPasswordCallback.SIGNATURE:

           // used to retrieve password for private key

           if ("serverkey".equals(id)) {

                pwcb.setPassword("serverpass");

            }

           break;

       }

    }

}

客户端CallbackHandler

package com.mms.webservice.test;

import java.io.IOException;

import javax.security.auth.callback.Callback;

import javax.security.auth.callback.CallbackHandler;

import javax.security.auth.callback.UnsupportedCallbackException;

import org.apache.ws.security.WSPasswordCallback;

publicclass ClientPasswordCallbackimplements CallbackHandler {

   publicvoid handle(Callback[] callbacks)throws IOException, UnsupportedCallbackException {

       WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];

       //服务器标识

        System.out.println("Server ID:"+pc.getIdentifier());

       // 设置返回给客户的服务器密码信息

        pc.setPassword("mima");

        pc.setIdentifier("cxf");

    }

}

然后还需要服务端启动类和和客户端启动类:

服务端启动类:

package com.server;

import java.util.HashMap;

import java.util.Map;

import org.apache.cxf.jaxws.JaxWsServerFactoryBean;

import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor;

import org.apache.ws.security.WSConstants;

import org.apache.ws.security.handler.WSHandlerConstants;

import com.mms.webservice.HelloWorldImpl;

import com.mms.webservice.test.ServerPasswordCallback;

publicclass Server {

   /**

    * @paramargs

    */

   publicstatic void main(String[] args) {

        Server server =new Server();

       //server.test();//没有安全验证WS

        server.testUsernameToken();//有安全验证WS

    }

   

   privatevoid test() {

        JaxWsServerFactoryBean server =new JaxWsServerFactoryBean();

//      server.getInInterceptors().add(new LoggingInInterceptor());

// server.getOutInterceptors().add(new LoggingOutInterceptor());

        server.setServiceClass(HelloWorldImpl.class);

        server.setAddress("http://localhost:9000/security");

        server.create();

    }

   private WSS4JInInterceptor getInInterceptor() {

        Map<String, Object> inProps =new HashMap<String, Object>();

        inProps.put(WSHandlerConstants.ACTION,

                WSHandlerConstants.USERNAME_TOKEN);

       // 密码类型 : plain text

        inProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);

       // 客户信息校验类设置

        inProps.put(WSHandlerConstants.PW_CALLBACK_CLASS,

                ServerPasswordCallback.class.getName());

       returnnew WSS4JInInterceptor(inProps);

    }

   

   privatevoid testUsernameToken() {

        JaxWsServerFactoryBean server =new JaxWsServerFactoryBean();

        //将回调拦截器加入server拦截器

        server.getInInterceptors().add(getInInterceptor());

       //server.getOutInterceptors().add(getOutInterceptor());

       

        server.setServiceClass(HelloWorldImpl.class);

        server.setAddress("http://localhost:9000/security");

        server.create();

    }

}

客户端启动类:

package com.client;

import java.util.HashMap;

import java.util.Map;

import org.apache.cxf.interceptor.LoggingInInterceptor;

import org.apache.cxf.interceptor.LoggingOutInterceptor;

import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;

import org.apache.ws.security.WSConstants;

import org.apache.ws.security.handler.WSHandlerConstants;

import com.mms.webservice.HelloWorld;

import com.mms.webservice.test.ClientPasswordCallback;

publicclass client {

   /**

    * @paramargs

    */

   publicstatic void main(String[] args) {

        JaxWsProxyFactoryBean factory =new JaxWsProxyFactoryBean();

       //打印日志

        factory.getOutInterceptors().add(new LoggingInInterceptor());

        factory.getInInterceptors().add(new LoggingOutInterceptor());

       

        factory.getOutInterceptors().add(getOutInterceptor());

        factory.setAddress("http://localhost:9000/security");

        factory.setServiceClass(HelloWorld.class);

       

       

        HelloWorld client = (HelloWorld)factory.create();

        System.out.println(client.sayHi("cxf"));

    }

   

   privatestatic WSS4JOutInterceptor getOutInterceptor() {

        Map<String, Object> outProps =new HashMap<String, Object>();

        outProps.put(WSHandlerConstants.ACTION,

                WSHandlerConstants.USERNAME_TOKEN);

       // 服务器用户标识

        outProps.put(WSHandlerConstants.USER,"IamServer");

       // 密码类型 : plain text

        outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);

       // 返回给客户端的密码信息

        outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS,

                ClientPasswordCallback.class.getName());

       returnnew WSS4JOutInterceptor(outProps);

    }

}

原理:利用CXF自身的拦截器

参考文章:http://hi.baidu.com/leezuu/blog/item/e502c3ae3de7da044a36d675.html

4、 CXFJSON应用

下面例子展示如何在ServerFactoryBeans应用JSON,首先创建一个HashMap属性来设置StAXXMLInputFactoryXMLOutputFactory

Map<String,Object> properties = new HashMap<String,Object>();

// Create a mapping between the XML namespaces and the JSON prefixes.

// The JSON prefix can be "" to specify that you don't want any prefix.

HashMap<String, String> nstojns = new HashMap<String,String>();

nstojns.put("http://customer.acme.com", "acme");

MappedXMLInputFactory xif = new MappedXMLInputFactory(nstojns);

properties.put(XMLInputFactory.class.getName(), xif);

MappedXMLOutputFactory xof = new MappedXMLOutputFactory(nstojns);

properties.put(XMLOutputFactory.class.getName(), xof);

设置Context-Type属性:

// Tell CXF to use a different Content-Type for the JSON endpoint
// This should probably be application/json, but text/plain allows
// us to view easily in a web browser.
properties.put("Content-Type", "text/plain");

最后创建服务:

// Build up the server factory bean
JaxWsServerFactoryBean sf = new JaxWsServerFactoryBean();
sf.setServiceClass(CustomerService.class);
// Use the HTTP Binding which understands the Java Rest Annotations
sf.setBindingId(HttpBindingFactory.HTTP_BINDING_ID);
sf.setAddress("http://localhost:8080/json");
sf.setServiceBean(new CustomerServiceImpl());
 
sf.setProperties(properties);
 
sf.create();

原文来自Apache官网:http://cxf.apache.org/docs/json-support.html

5、 CXF之嵌入Jetty

这次只介绍服务端,嵌入Jetty不需要导入Jettyjar包,只需要导入CXF的包即可(CXF已把Jetty整合)。

首先的创建服务接口和服务实现类,这里不再重复,参照前面例子。

其次创建一个Jetty启动类,用来启动Jetty并且发布Web服务。

package com.server;

import javax.xml.ws.Endpoint;

import org.apache.cxf.jaxws.JaxWsServerFactoryBean;

import org.eclipse.jetty.server.Connector;

import org.eclipse.jetty.server.nio.SelectChannelConnector;

import com.service.HelloWorldImpl;

publicclass JettyServer {

   publicstatic void main(String[] args){

       new JettyServer();

    }

   

   private JettyServer(){

       System.out.println(System.getProperty("user.dir"));

        String app =System.getProperty("user.dir");//得到项目路径

       

        org.eclipse.jetty.server.Server server

            =new org.eclipse.jetty.server.Server();//新建一个Jetty服务器

        Connector conn =new SelectChannelConnector();//新建Connector组件

        conn.setHost("127.0.0.1");

        conn.setPort(9000);

        server.setConnectors(new Connector[]{conn});//插入服务器主件中

       

        org.eclipse.jetty.server.handler.ContextHandler context

            =new org.eclipse.jetty.server.handler.ContextHandler();//新建Handler组件

        context.setContextPath("/");//Web应用的上下文跟路径

        context.setResourceBase(app);

        server.setHandler(context);//插入服务器主件中

       

        org.eclipse.jetty.util.thread.QueuedThreadPool pool

            =new org.eclipse.jetty.util.thread.QueuedThreadPool();//创建线程池组件

        pool.setMaxThreads(100);//设置最大线程数

        pool.setMinThreads(10);//设置最小线程数

        server.setThreadPool(pool);

       

       //发布Web服务

       //Endpoint.publish("http://127.0.0.1:9000/WS-CXF-Jetty", new HelloWorldImpl());

        JaxWsServerFactoryBean wsServer =new JaxWsServerFactoryBean();

        wsServer.setAddress("http://127.0.0.1:9000/WS-CXF-Jetty");

        wsServer.setServiceBean(new HelloWorldImpl());

        wsServer.create();

       

       try {

            server.start();

           //System.out.println(server.isStarted());

        }catch (Exception e) {

            e.printStackTrace();

        }

    }

}

参考文档:http://liuskysun.blog.163.com/blog/static/9981297820101023139723/

5、 关于wsdl2java自动生成客户端

利用wsdl2java生成的客户端,有个继承javax.xml.ws.Service的类,此方法的3个构造函数会报错(The constructor Service(URL, QName, WebServiceFeature[]) is undefined),原因是:jdk中有个javax.xml.ws.Service(低版本),而CXFgeronimo-jaxws_2.2_spec-1.0.jar中也有个javax.xml.ws.Service(高版本),而类里默认调用的是jdk(低版本)的Service,故报错!

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值