一、关于CXF的历史
网上可以很轻松的搜到相关的CXF历史。我就简单的说一下:CXF是一个实现Web Service的框架,由Celtix 和XFire合并而成,目前是Apache的顶级项目。
webservice领域比较有名的框架目前主要还有Axis2。相比较而言,CXF更新速度较快,而Axis2已经好久没更新了。
二、使用 CXF内置的 Jetty发布 WS服务端
学习先从官网开始:http://cxf.apache.org/,左侧有个user's guide,点击进入。
官网上说,CXF目前主要有三种服务方式:SOAP、REST-ful、CORBA。
这篇博文用的是第一种服务方式,根据官方指导可知,CXF官网推荐我们使用maven构建CXF的应用,那么我们就使用maven。
不会用maven的同学可以参考http://www.voidcn.com/article/p-nggcpdwp-kz.html
1.第一步就配置 Maven 依赖
下面是我的pom.xml。每個人可能不完全一样,但是cxf-rt-frontend-jaxws和jetty依赖不能少,也可直接复制官网提供的pom.xml,那个比较全。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>CXF</groupId>
<artifactId>CXF</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>CXF</name>
<description />
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<cxf.version>3.0.3</cxf.version>
</properties>
<build>
<sourceDirectory>src</sourceDirectory>
<resources>
<resource>
<directory>src</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.2</version>
<configuration>
<warSourceDirectory>${basedir}/WebRoot</warSourceDirectory>
<version>3.0</version>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<!-- CXF -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>${cxf.version}</version>
</dependency>
</dependencies>
</project>
不想使用 Maven的童鞋,那么就需要从以下地址下载 CXF 的相关 jar 包,并将其放入应用中。
http://cxf.apache.org/download.html (binary distribution是jar包,而source distribution是包含源文件的)
2.编写服务接口和接口实现
package com.alibaba.cxf;
import javax.jws.WebService;
/**
* @author tfj
* 2015年1月7日
* WS 接口
*/
@WebService
public interface HelloWorld {
String sayHi(String name);
}
package com.alibaba.cxf.impl;
import javax.jws.WebService;
import com.alibaba.cxf.HelloWorld;
/**
* @author tfj
* 2015年1月7日
* WS 接口实现
*/
@WebService
public class HelloWorldImpl implements HelloWorld{
@Override
public String sayHi(String name) {
return "hello " + name;
}
}
这里简化了实现类上的 WebService 注解的配置,让 CXF 自动为我们取默认值即可。
3.发布webService服务(这里以JAX-WS方式发布)
package com.alibaba.cxf;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
import com.alibaba.cxf.impl.HelloWorldImpl;
/**
* @author tfj
* 2015年1月7日
* 发布服务
*/
public class JaxWsServer {
public static void main(String[] args) {
HelloWorldImpl implementor = new HelloWorldImpl();
JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();
// 除了http://localhost部分其他部分可以随便写,但格式不能乱 http://IP:PORT/NAME
factory.setAddress("http://localhost:8080/ws/hello");
factory.setServiceClass(HelloWorld.class);//可省,但不建议,因为可能会有些小问题
factory.setServiceBean(implementor);
// //LoggingInInterceptor和LoggingOutInterceptor是日志拦截器,用于输入和输出时显示日志
factory.getInInterceptors().add(new LoggingInInterceptor());
factory.getOutInterceptors().add(new LoggingOutInterceptor());
factory.create();
System.out.println("ws is published");
}
}
运行该类之后,就相当于发布了webservice,我们可以在浏览器中输入http://localhost:8080/ws/hello?wsdl来查看WSDL。
看到这里,第一个简单的demo出来了,但是这种方式显然不适用于生产环境,通常情况下我们还是需要依靠于 Tomcat 与 Spring。
三、在 Web 容器中使用 Spring + CXF 发布 WS服务端
官网上这部分给的例子比较旧,所以这里我参考的是http://my.oschina.net/huangyong/blog/286439。
1.同样的,在maven中加入spring的依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
2.编写服务接口和接口实现。
这里由于要和spring整合,所以加入component注解,便于Spring IOC容器扫描。
package com.alibaba.cxf.impl;
import javax.jws.WebService;
import org.springframework.stereotype.Component;
import com.alibaba.cxf.HelloWorld;
/**
* @author tfj
* 2015年1月7日
* WS 接口实现
*/
@Component
@WebService
public class HelloWorldImpl implements HelloWorld{
@Override
public String sayHi(String name) {
return "hello " + name;
}
}
3.配置 web.xml。
<?xml version="1.0" encoding="UTF-8"?>
<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_3_0.xsd"
id="WebApp_ID" version="3.0">
<!-- Spring -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- CXF -->
<servlet>
<servlet-name>cxf</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>cxf</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
4.配置 Spring.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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:component-scan base-package="com.alibaba.cxf" />
<import resource="spring-cxf.xml" />
</beans>
告诉spring扫描路径(根据自己的包名写),并将cxf的配置文件分离
5.配置 Spring-cxf.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:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
<jaxws:endpoint id="helloWorld" implementor="com.alibaba.cxf.impl.HelloWorldImpl" address="/spring/hello"/>
</beans>
6.发布webservice
将应用部署到 Tomcat 中,在浏览器中输入以下地址可进入 CXF 控制台:
http://127.0.0.1:8080/CXF/

四、构建WS客户端
上面两个方法主要讲的是构建WS服务端,即通过 CXF对外发布了 WS,下面要做的事情就是用 WS客户端来访问和调用WS了。
1.静态代理客户端
这种方法,需要告诉访问者你的url、服务接口类(Helloworld)、服务接口名,显然太多了。一般而言,访问者只需要知道url和调用方法就行了,所以有了下面的方法
/**
* 静态代理客户端
*/
public static void JaxWsClient(String address) {
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setAddress(address);
factory.setServiceClass(HelloWorld.class);
HelloWorld helloService = factory.create(HelloWorld.class);
String result = helloService.sayHi("JaxWsClient");
System.out.println(result);
}
2.动态代理客户端
/**
* 通用动态代理客户端
*/
public static void DynamicClient(String address) {
//CXF发布用的是业务类(HelloWorldImpl.java),那么默认的命名空间就会是业务类所在包(路径),
//而对外界暴露的则是接口类(HelloWorld.java),那么对于客户端(第三方)调用访问时,需要按照接口类所在包(路径)进行命名空间的定义
QName opName = new QName("http://cxf.alibaba.com/","sayHi"); // 指定到接口类所在包
address = address+"?wsdl";
DynamicClientFactory factory = DynamicClientFactory.newInstance();
Client client = factory.createClient(address);
try {
Object[] results = client.invoke(opName,"DynamicClient");
System.out.println(results[0]);
} catch (Exception e) {
e.printStackTrace();
}
//如果接口和实现在同一路径下,就使用下面的代码.
// address = address+"?wsdl";
// DynamicClientFactory factory = DynamicClientFactory.newInstance();
// Client client = factory.createClient(address);
// try {
// Object[] results = client.invoke("sayHi","DynamicClient");
// System.out.println(results[0]);
// } catch (Exception e) {
// e.printStackTrace();
// }
}
3.基于spring的客户端
/**
* spring客户端
*/
public static void SpringClient() {
context = new ClassPathXmlApplicationContext("spring-client.xml");
HelloWorld helloService = context.getBean("helloWorld",HelloWorld.class);
String result = helloService.sayHi("SpringClient");
System.out.println(result);
}
到此CXF的基础知识已经讲了,剩下的就是扩展了,比如流行的RESTFUL啊、Security啊等等。
代码下载地址:http://download.csdn.net/detail/tonytfjing/8341849