首先:什么是CXF?为什么要用CXF?
CXF 包含了大量的功能特性,但是主要集中在以下几个方面:支持 Web Services 标准:CXF 支持多种 Web Services 标准,包含 SOAP、Basic Profile、WS-Addressing、WS-Policy、WS-ReliableMessaging 和 WS-Security。Frontends:CXF 支持多种“Frontend”编程模型,CXF 实现了 JAX-WS API (遵循 JAX-WS 2.0 TCK 版本),它也包含一个“simple frontend”允许客户端和 EndPoint 的创建,而不需要 Annotation 注解。CXF 既支持 WSDL 优先开发,也支持从 Java 的代码优先开发模式。容易使用: CXF 设计得更加直观与容易使用。有大量简单的 API 用来快速地构建代码优先的 Services,各种 Maven 的插件也使集成更加容易,支持 JAX-WS API ,支持 Spring 2.0 更加简化的 XML 配置方式,等等。支持二进制和遗留协议:CXF 的设计是一种可插拨的架构,既可以支持 XML ,也可以支持非 XML 的类型绑定,比如:JSON 和 CORBA。
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接口:
1 @WebService 2 public interface HelloService { 3 public String sayHi(String text); 4 public String getUser(User user); 5 public List<User> getListUser(); 6 }
需要在接口头部注明一个"WebService"注解,表示这是一个webservice。
至于User类则是一个序列化的javabean(在对象传输过程建议尽量序列化,熟悉java io的朋友应该清楚这点):
1 public class User implements Serializable{ 2 private static final long serialVersionUID = 1001881900957402607L; 3 4 private Integer id; 5 private String name; 6 7 getter,setter... 8 }
然后编写接口的实现类:
1 @WebService(endpointInterface = "com.bless.ws.HelloService", serviceName = "HelloService",portName="HelloServicePort") 2 public class HelloServiceImpl implements HelloService { 3 4 @Override 5 public String sayHi(String text) { 6 System.out.println("sayHi called..."); 7 return "Hi :" + text; 8 } 9 10 @Override 11 public String getUser(User user) { 12 System.out.println("sayUser called..."); 13 return "User:[id=" + user.getId() + "][name=" + user.getName() + "]"; 14 } 15 16 @Override 17 public List<User> getListUser() { 18 System.out.println("getListUser called..."); 19 List<User> lst = new ArrayList<User>(); 20 lst.add(new User(2, "u2")); 21 lst.add(new User(3, "u3")); 22 lst.add(new User(4, "u4")); 23 lst.add(new User(5, "u5")); 24 lst.add(new User(6, "u6")); 25 return lst; 26 } 27 28 }
此时注解WebService内还有三个属性:
endpointInterface表示webservice接口名,因为一个类可以继承多个接口,你必须指明哪个是webservice接口
serviceName:表示当前webservice的别名
portName:表示当前webservice的端口名
这些属性定义好之后,在wsdl中是能看到的,如果不定义,cxf会配置默认的别名和端口名
最后一步部署webservice:
1 public class Server { 2 3 protected Server() throws Exception { 4 // START SNIPPET: publish 5 System.out.println("Starting Server"); 6 HelloServiceImpl implementor = new HelloServiceImpl(); 7 String address = "http://localhost:8111/helloWorld"; 8 Endpoint.publish(address, implementor); 9 // END SNIPPET: publish 10 } 11 12 public static void main(String[] args) throws Exception { 13 new Server(); 14 System.out.println("Server ready..."); 15 16 Thread.sleep(5 * 60 * 1000); 17 System.out.println("Server exiting"); 18 System.exit(0); 19 } 20 }
web service是需要部署到服务器的,通过Endpoint.publish方法部署的话,我估计是部署到jetty上的,具体神马情况,因为个人经验不足在这不胡说了。通过运行main函数就可以启动服务了,检验服务是否启动,可以访问如下地址:http://localhost:8111/helloWorld?wsdl,如果能显示正确的xml信息则表示服务启动成功。
最后写一个客户端程序调用web service:
1 public final class Client { 2 3 private static final QName SERVICE_NAME 4 = new QName("http://ws.bless.com/", "HelloService"); 5 private static final QName PORT_NAME 6 = new QName("http://ws.bless.com/", "HelloServicePort"); 7 8 9 private Client() { 10 } 11 12 public static void main(String args[]) throws Exception { 13 Service service = Service.create(SERVICE_NAME); 14 // Endpoint Address 15 String endpointAddress = "http://localhost:8111/helloWorld"; 16 17 // Add a port to the Service 18 service.addPort(PORT_NAME, SOAPBinding.SOAP11HTTP_BINDING, endpointAddress); 19 20 HelloService hw = service.getPort(HelloService.class); 21 System.out.println(hw.sayHi("World")); 22 23 System.out.println(hw.getUser(new User(1, "kaka"))); 24 25 for(User user : hw.getListUser()){ 26 System.out.println("List User [id:"+user.getId()+"][name:"+user.getName()+"]"); 27 } 28 } 29 30 }
测试:
首先启动server,如果没问题的话,再启动clien,大家可以看控制台的效果。
3、CXF与spring整合:
熟悉spring的朋友应该知道spring的IOC管理对象非常强大,那么cxf与spring整合也是源于此目的:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" 4 xsi:schemaLocation=" 5 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 6 http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> 7 8 <import resource="classpath:META-INF/cxf/cxf.xml" /> 9 <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" /> 10 <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> 11 12 <jaxws:endpoint id="helloWorld" implementor="com.bless.ws.HelloServiceImpl" address="http://localhost:8080/webservice/helloService" /> 13 14 <jaxws:client id="helloClient" serviceClass="com.bless.ws.HelloService" address="http://localhost:8080/webservice/helloService" /> 15 16 </beans>
大家可以通过java代码测试(测试时把上一步配置的beans.xml文件放在src根下面):
1 public class SpringTest { 2 public static void main(String[] args) { 3 // START SNIPPET: client 4 ClassPathXmlApplicationContext context 5 = new ClassPathXmlApplicationContext("beans.xml"); 6 7 HelloService client = (HelloService)context.getBean("helloClient"); 8 9 String response = client.sayHi("Joe"); 10 System.out.println("Response: " + response); 11 System.exit(0); 12 // END SNIPPET: client 13 } 14 }
如果是web项目,那么你需要配置web.xml文件:
1 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 2 xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 3 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 4 id="WebApp_ID" version="2.5"> 5 <display-name>CxfDemo</display-name> 6 7 <context-param> 8 <param-name>contextConfigLocation</param-name> 9 <param-value>WEB-INF/beans.xml</param-value> 10 </context-param> 11 12 <!--Spring ApplicationContext 载入 ,必须--> 13 <listener> 14 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 15 </listener> 16 17 <!-- Spring 刷新Introspector防止内存泄露 --> 18 <listener> 19 <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class> 20 </listener> 21 22 <servlet> 23 <servlet-name>CXFServlet</servlet-name> 24 <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> 25 <load-on-startup>1</load-on-startup> 26 </servlet> 27 28 <servlet-mapping> 29 <servlet-name>CXFServlet</servlet-name> 30 <url-pattern>/webservice/*</url-pattern> 31 </servlet-mapping> 32 33 </web-app>