天天看點

【轉】關于CXF WebService3.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,那個比較全。

[html] view plain copy print ?

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  2.     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
  3.     <modelVersion>4.0.0</modelVersion>  
  4.     <groupId>CXF</groupId>  
  5.     <artifactId>CXF</artifactId>  
  6.     <version>1.0-SNAPSHOT</version>  
  7.     <packaging>war</packaging>  
  8.     <name>CXF</name>  
  9.     <description />  
  10.     <properties>  
  11.         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
  12.         <cxf.version>3.0.3</cxf.version>  
  13.     </properties>  
  14.     <build>  
  15.         <sourceDirectory>src</sourceDirectory>  
  16.         <resources>  
  17.             <resource>  
  18.                 <directory>src</directory>  
  19.                 <excludes>  
  20.                     <exclude>**/*.java</exclude>  
  21.                 </excludes>  
  22.             </resource>  
  23.         </resources>  
  24.         <plugins>  
  25.             <plugin>  
  26.                 <artifactId>maven-compiler-plugin</artifactId>  
  27.                 <version>2.3.2</version>  
  28.                 <configuration>  
  29.                     <source>1.7</source>  
  30.                     <target>1.7</target>  
  31.                 </configuration>  
  32.             </plugin>  
  33.             <plugin>  
  34.                 <artifactId>maven-war-plugin</artifactId>  
  35.                 <version>2.2</version>  
  36.                 <configuration>  
  37.                     <warSourceDirectory>${basedir}/WebRoot</warSourceDirectory>  
  38.                     <version>3.0</version>  
  39.                     <failOnMissingWebXml>false</failOnMissingWebXml>  
  40.                 </configuration>  
  41.             </plugin>  
  42.         </plugins>  
  43.     </build>  
  44.     <dependencies>  
  45.         <!-- CXF -->  
  46.         <dependency>  
  47.             <groupId>org.apache.cxf</groupId>  
  48.             <artifactId>cxf-rt-frontend-jaxws</artifactId>  
  49.             <version>${cxf.version}</version>  
  50.         </dependency>  
  51.         <dependency>  
  52.             <groupId>org.apache.cxf</groupId>  
  53.             <artifactId>cxf-rt-transports-http-jetty</artifactId>  
  54.             <version>${cxf.version}</version>  
  55.         </dependency>  
  56.     </dependencies>  
  57. </project>  
<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.編寫服務接口和接口實作

[java] view plain copy print ?

  1. package com.alibaba.cxf;  
  2. import javax.jws.WebService;  
  3. @WebService  
  4. public interface HelloWorld {  
  5.     String sayHi(String name);  
  6. }  
package com.alibaba.cxf;

import javax.jws.WebService;

/**
 * @author tfj
 * 2015年1月7日
 * WS 接口
 */
@WebService
public interface HelloWorld {
    String sayHi(String name);
}
           

[java] view plain copy print ?

  1. package com.alibaba.cxf.impl;  
  2. import javax.jws.WebService;  
  3. import com.alibaba.cxf.HelloWorld;  
  4. @WebService  
  5. public class HelloWorldImpl implements HelloWorld{  
  6.     @Override  
  7.     public String sayHi(String name) {  
  8.          return "hello " + name;  
  9.     }  
  10. }  
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方式釋出)

[java] view plain copy print ?

  1. package com.alibaba.cxf;  
  2. import org.apache.cxf.interceptor.LoggingInInterceptor;  
  3. import org.apache.cxf.interceptor.LoggingOutInterceptor;  
  4. import org.apache.cxf.jaxws.JaxWsServerFactoryBean;  
  5. import com.alibaba.cxf.impl.HelloWorldImpl;  
  6. public class JaxWsServer {  
  7.     public static void main(String[] args) {  
  8.         HelloWorldImpl implementor = new HelloWorldImpl();  
  9.         JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();  
  10.         // 除了http://localhost部分其他部分可以随便寫,但格式不能亂 http://IP:PORT/NAME  
  11.         factory.setAddress("http://localhost:8080/ws/hello");  
  12.         factory.setServiceClass(HelloWorld.class);//可省,但不建議,因為可能會有些小問題  
  13.         factory.setServiceBean(implementor);  
  14. //        //LoggingInInterceptor和LoggingOutInterceptor是日志攔截器,用于輸入和輸出時顯示日志  
  15.         factory.getInInterceptors().add(new LoggingInInterceptor());  
  16.         factory.getOutInterceptors().add(new LoggingOutInterceptor());  
  17.         factory.create();  
  18.         System.out.println("ws is published");  
  19.     }  
  20. }  
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的依賴

[html] view plain copy print ?

  1. <dependency>  
  2.     <groupId>org.springframework</groupId>  
  3.     <artifactId>spring-context</artifactId>  
  4.     <version>4.1.4.RELEASE</version>  
  5. </dependency>  
  6. <dependency>  
  7.     <groupId>org.springframework</groupId>  
  8.     <artifactId>spring-web</artifactId>  
  9.     <version>4.1.4.RELEASE</version>  
  10. </dependency>  
<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容器掃描。

[java] view plain copy print ?

  1. package com.alibaba.cxf.impl;  
  2. import javax.jws.WebService;  
  3. import org.springframework.stereotype.Component;  
  4. import com.alibaba.cxf.HelloWorld;  
  5. @Component  
  6. @WebService  
  7. public class HelloWorldImpl implements HelloWorld{  
  8.     @Override  
  9.     public String sayHi(String name) {  
  10.          return "hello " + name;  
  11.     }  
  12. }  
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。

[html] view plain copy print ?

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  3.     xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"  
  4.     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"  
  5.     id="WebApp_ID" version="3.0">  
  6.     <!-- Spring -->  
  7.     <context-param>  
  8.         <param-name>contextConfigLocation</param-name>  
  9.         <param-value>/WEB-INF/spring.xml</param-value>  
  10.     </context-param>  
  11.     <listener>  
  12.         <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
  13.     </listener>  
  14.     <!-- CXF -->  
  15.     <servlet>  
  16.         <servlet-name>cxf</servlet-name>  
  17.         <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>  
  18.     </servlet>  
  19.     <servlet-mapping>  
  20.         <servlet-name>cxf</servlet-name>  
  21.         <url-pattern>/*</url-pattern>  
  22.     </servlet-mapping>  
  23. </web-app>  
<?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。

[html] view plain copy print ?

  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:context="http://www.springframework.org/schema/context"  
  4.     xsi:schemaLocation="http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans-4.0.xsd  
  5.        http://www.springframework.org/schema/context   http://www.springframework.org/schema/context/spring-context-4.0.xsd">  
  6.     <context:component-scan base-package="com.alibaba.cxf" />  
  7.     <import resource="spring-cxf.xml" />  
  8. </beans>   
<?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。

[html] view plain copy print ?

  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"  
  4.        xmlns:jaxws="http://cxf.apache.org/jaxws"  
  5.        xsi:schemaLocation="http://www.springframework.org/schema/beans  
  6.        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd  
  7.        http://cxf.apache.org/jaxws  
  8.        http://cxf.apache.org/schemas/jaxws.xsd">  
  9.     <jaxws:endpoint id="helloWorld" implementor="com.alibaba.cxf.impl.HelloWorldImpl" address="/spring/hello"/>  
  10. </beans>  
<?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/

【轉】關于CXF WebService3.0

四、建構WS用戶端

上面兩個方法主要講的是建構WS服務端,即通過 CXF對外釋出了 WS,下面要做的事情就是用 WS用戶端來通路和調用WS了。

1.靜态代理用戶端

這種方法,需要告訴通路者你的url、服務接口類(Helloworld)、服務接口名,顯然太多了。一般而言,通路者隻需要知道url和調用方法就行了,是以有了下面的方法

[java] view plain copy print ?

  1. public static void JaxWsClient(String address) {  
  2.     JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();  
  3.     factory.setAddress(address);  
  4.     factory.setServiceClass(HelloWorld.class);  
  5.     HelloWorld helloService = factory.create(HelloWorld.class);  
  6.     String result = helloService.sayHi("JaxWsClient");  
  7.     System.out.println(result);  
  8. }  
/**
	 * 靜态代理用戶端
	 */
	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.動态代理用戶端

[html] view plain copy print ?

  1.     public static void DynamicClient(String address) {  
  2.         //CXF釋出用的是業務類(HelloWorldImpl.java),那麼預設的命名空間就會是業務類所在包(路徑),  
  3.         //而對外界暴露的則是接口類(HelloWorld.java),那麼對于用戶端(第三方)調用通路時,需要按照接口類所在包(路徑)進行命名空間的定義  
  4.         QName opName = new QName("http://cxf.alibaba.com/", "sayHi");  // 指定到接口類所在包  
  5.         address = address+"?wsdl";  
  6.         DynamicClientFactory factory = DynamicClientFactory.newInstance();  
  7.         Client client = factory.createClient(address);  
  8.         try {  
  9.             Object[] results = client.invoke(opName, "DynamicClient");  
  10.             System.out.println(results[0]);  
  11.         } catch (Exception e) {  
  12.             e.printStackTrace();  
  13.         }  
  14.         //如果接口和實作在同一路徑下,就使用下面的代碼.  
  15. //      address = address+"?wsdl";  
  16. //      DynamicClientFactory factory = DynamicClientFactory.newInstance();  
  17. //      Client client = factory.createClient(address);  
  18. //      try {  
  19. //          Object[] results = client.invoke("sayHi", "DynamicClient");  
  20. //          System.out.println(results[0]);  
  21. //      } catch (Exception e) {  
  22. //          e.printStackTrace();  
  23. //      }  
  24.     }  
/**
	 * 通用動态代理用戶端
	 */
	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的用戶端

[java] view plain copy print ?

  1. public static void SpringClient() {  
  2.     context = new ClassPathXmlApplicationContext("spring-client.xml");  
  3.     HelloWorld helloService = context.getBean("helloWorld", HelloWorld.class);  
  4.        String result = helloService.sayHi("SpringClient");  
  5.        System.out.println(result);  
  6. }  
/**
	 * 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