首页 > 代码库 > webservice-CXF3.0

webservice-CXF3.0

一、关于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://blog.csdn.net/tonytfjing/article/details/39006087

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

webservice-CXF3.0