`

CXF框架入门实例

阅读更多

CXF是apache旗下的开源框架,由Celtix + XFire这两门经典的框架合成,是一套非常流行的web service框架。

它提供了JAX-WS的全面支持,并且可以根据实际项目的需要,采用代码优先(Code First)或者 WSDL 优先(WSDL First)来轻松地实现 Web Services 的发布和使用,同时它能与spring进行完美结合。

在apache cxf官网提供了cxf较全面的帮助文档,英语教好的童鞋可以到这个地址学习:http://cxf.apache.org/docs/index.html

 

下面就以官网教程为例,简单介绍下cxf的使用。

 

1、依赖的jar包

去官网下载cxf压缩文件:http://cxf.apache.org/download.html

解压后,把apache-cxf-2.4.1\lib目录下的jar包引用到java项目中

 

2、JAX-WS简单实例

 首先编写一个ws接口:

@WebService
public interface HelloService {
	public String sayHi(String text);
	public String getUser(User user);
	public List<User> getListUser();
}

 

需要在接口头部注明一个"WebService"注解,表示这是一个webservice。

至于User类则是一个序列化的javabean(在对象传输过程建议尽量序列化,熟悉java io的朋友应该清楚这点):

public class User implements Serializable{
	private static final long serialVersionUID = 1001881900957402607L;
	
	private Integer id;
	private String name;

   getter,setter...
}

 

然后编写接口的实现类:

@WebService(endpointInterface = "com.bless.ws.HelloService", serviceName = "HelloService",portName="HelloServicePort")
public class HelloServiceImpl implements HelloService {

	@Override
	public String sayHi(String text) {
		System.out.println("sayHi called...");
		return "Hi :" + text;
	}

	@Override
	public String getUser(User user) {
		System.out.println("sayUser called...");
		return "User:[id=" + user.getId() + "][name=" + user.getName() + "]";
	}

	@Override
	public List<User> getListUser() {
		System.out.println("getListUser called...");
		List<User> lst = new ArrayList<User>();
		lst.add(new User(2, "u2"));
		lst.add(new User(3, "u3"));
		lst.add(new User(4, "u4"));
		lst.add(new User(5, "u5"));
		lst.add(new User(6, "u6"));
		return lst;
	}

}

 此时注解WebService内还有三个属性:

endpointInterface表示webservice接口名,因为一个类可以继承多个接口,你必须指明哪个是webservice接口

serviceName:表示当前webservice的别名

portName:表示当前webservice的端口名

这些属性定义好之后,在wsdl中是能看到的,如果不定义,cxf会配置默认的别名和端口名

 

最后一步部署webservice:

public class Server {
	
	protected Server() throws Exception {
        // START SNIPPET: publish
        System.out.println("Starting Server");
        HelloServiceImpl implementor = new HelloServiceImpl();
        String address = "http://localhost:8111/helloWorld";
        Endpoint.publish(address, implementor);
        // END SNIPPET: publish
    }
	
	public static void main(String[] args) throws Exception {
		new Server();
        System.out.println("Server ready...");

        Thread.sleep(5 * 60 * 1000);
        System.out.println("Server exiting");
        System.exit(0);
	}
}

 web service是需要部署到服务器的,通过Endpoint.publish方法部署的话,我估计是部署到jetty上的,具体神马情况,因为个人经验不足在这不胡说了。通过运行main函数就可以启动服务了,检验服务是否启动,可以访问如下地址:http://localhost:8111/helloWorld?wsdl,如果能显示正确的xml信息则表示服务启动成功。

 

最后写一个客户端程序调用web service:

public final class Client {

    private static final QName SERVICE_NAME 
        = new QName("http://ws.bless.com/", "HelloService");
    private static final QName PORT_NAME 
        = new QName("http://ws.bless.com/", "HelloServicePort");


    private Client() {
    } 

    public static void main(String args[]) throws Exception {
        Service service = Service.create(SERVICE_NAME);
        // Endpoint Address
        String endpointAddress = "http://localhost:8111/helloWorld";

        // Add a port to the Service
        service.addPort(PORT_NAME, SOAPBinding.SOAP11HTTP_BINDING, endpointAddress);
        
        HelloService hw = service.getPort(HelloService.class);
        System.out.println(hw.sayHi("World"));

        System.out.println(hw.getUser(new User(1, "kaka")));
        
        for(User user : hw.getListUser()){
        	System.out.println("List User [id:"+user.getId()+"][name:"+user.getName()+"]");
        }
    }

}

 

 

测试:

首先启动server,如果没问题的话,再启动clien,大家可以看控制台的效果。

 

 

3、CXF与spring整合:

熟悉spring的朋友应该知道spring的IOC管理对象非常强大,那么cxf与spring整合也是源于此目的:

<?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:jaxws="http://cxf.apache.org/jaxws"
	xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.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="helloWorld" implementor="com.bless.ws.HelloServiceImpl" address="http://localhost:8080/webservice/helloService" />
	
	<jaxws:client id="helloClient" serviceClass="com.bless.ws.HelloService" address="http://localhost:8080/webservice/helloService" />
	
</beans>

 

大家可以通过java代码测试(测试时把上一步配置的beans.xml文件放在src根下面):

public class SpringTest {
	public static void main(String[] args) {
		// START SNIPPET: client
        ClassPathXmlApplicationContext context 
            = new ClassPathXmlApplicationContext("beans.xml");
        
        HelloService client = (HelloService)context.getBean("helloClient");

        String response = client.sayHi("Joe");
        System.out.println("Response: " + response);
        System.exit(0);
        // END SNIPPET: client
	}
}

 

 

如果是web项目,那么你需要配置web.xml文件:

 

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5">
	<display-name>CxfDemo</display-name>

	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>WEB-INF/beans.xml</param-value>
	</context-param>

	<!--Spring ApplicationContext 载入 ,必须-->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- Spring 刷新Introspector防止内存泄露 -->
	<listener>
		<listener-class>org.springframework.web.util.IntrospectorCleanupListener</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>/webservice/*</url-pattern>
	</servlet-mapping>

</web-app>

 

7
3
分享到:
评论
7 楼 jonyzhou94 2017-09-28  
1987_ming 写道
1987_ming 写道
System.out.println(hw.getUser(new User(1, "kaka")));  这段报错呢~~~Caused by: org.apache.cxf.binding.soap.SoapFault: Unmarshalling Error: null 这个错误~~~

找到这个问题的原因了,POJO类中如果已经指定了一个构造器,那么一定要再指定一个public的空构造器,否则会报错。具体为什么没有看过源码,不敢乱说。

你在SERVICE_NAME和PORT_NAME里面的配置问题.那个路径应该为你的HelloService接口的反置位置
6 楼 1987_ming 2016-03-22  
1987_ming 写道
System.out.println(hw.getUser(new User(1, "kaka")));  这段报错呢~~~Caused by: org.apache.cxf.binding.soap.SoapFault: Unmarshalling Error: null 这个错误~~~

找到这个问题的原因了,POJO类中如果已经指定了一个构造器,那么一定要再指定一个public的空构造器,否则会报错。具体为什么没有看过源码,不敢乱说。
5 楼 1987_ming 2016-03-22  
System.out.println(hw.getUser(new User(1, "kaka")));  这段报错呢~~~Caused by: org.apache.cxf.binding.soap.SoapFault: Unmarshalling Error: null 这个错误~~~
4 楼 去香山看枫叶 2015-07-29  
白糖_ 写道
234390216 写道
看了官网的介绍,还是没有明白这东西在具体项目中到底有什么用?还请楼主给我解释一下,谢谢!

我也是刚学习,就我最近看的资料,我是这样理解的:
CXF的目的是为了开发web service,web service是SOAP的具体实现,web service的一个主要作用是解决不同语言通信的问题。举个例子,现在iteye不是希望和csdn整合吗(iteye用的ruby语言,csdn用的asp.net),你看iteye上的通告,以后可以用csdn帐号登录了。那么这个登录系统肯定是在iteye下的,但是帐号密码一定要发送给csdn验证,ruby怎么把帐号密码发给asp.net?不同语言怎么识别?这里就用到web service了,因为web service是一个统一标准,asp.net可以定义一个登录验证的web service接口,提供一个checkLogin方法,参数是传入帐号密码,具体实现是asp.net内部的事,如果验证成功则返回true即可:public bool checkLogin(string loginCode,string password); 因为web service本身规则比较多,为了减少我们程序员的负担,往往会有一些框架来实现web service,比如java的CXF,.net也会有自己的框架,最后web service编写成功后通过部署到服务器,ruby就可以通过web service的形式调用asp.net代码了,这样就实现了不同语言的通信。
以上是个人理解。

我类个去,说得太明白,不敢直视。
3 楼 youyouyoushen 2013-06-27  
 
2 楼 白糖_ 2011-06-27  
234390216 写道
看了官网的介绍,还是没有明白这东西在具体项目中到底有什么用?还请楼主给我解释一下,谢谢!

我也是刚学习,就我最近看的资料,我是这样理解的:
CXF的目的是为了开发web service,web service是SOAP的具体实现,web service的一个主要作用是解决不同语言通信的问题。举个例子,现在iteye不是希望和csdn整合吗(iteye用的ruby语言,csdn用的asp.net),你看iteye上的通告,以后可以用csdn帐号登录了。那么这个登录系统肯定是在iteye下的,但是帐号密码一定要发送给csdn验证,ruby怎么把帐号密码发给asp.net?不同语言怎么识别?这里就用到web service了,因为web service是一个统一标准,asp.net可以定义一个登录验证的web service接口,提供一个checkLogin方法,参数是传入帐号密码,具体实现是asp.net内部的事,如果验证成功则返回true即可:public bool checkLogin(string loginCode,string password); 因为web service本身规则比较多,为了减少我们程序员的负担,往往会有一些框架来实现web service,比如java的CXF,.net也会有自己的框架,最后web service编写成功后通过部署到服务器,ruby就可以通过web service的形式调用asp.net代码了,这样就实现了不同语言的通信。
以上是个人理解。
1 楼 234390216 2011-06-27  
看了官网的介绍,还是没有明白这东西在具体项目中到底有什么用?还请楼主给我解释一下,谢谢!

相关推荐

Global site tag (gtag.js) - Google Analytics