1. 程式人生 > >在java中使用spring整合cxf實現webservice

在java中使用spring整合cxf實現webservice

java中實現webservice有兩種常用的方式,一種是cxf,另一種是axis。這兩種方式的區別大家可以自己在網上找找參考一下。cxf可以與spring進行整合,是一款不錯的webservice產品。今天給大家講解一下使用spring整合cxf實現webservice的方法。

1 建立伺服器端程式

1.1 新建一個web工程

1.1.1 工程環境所依賴的各軟體的版本

首先需要新建一個web工程,工程執行環境為:

  • java:1.7.0_65

  • tomcat:apache-tomcat-6.0.47

  • eclipse:Luna Service Release 2 (4.4.2)

  • cxf:3.1.8

  • 作業系統:win7

先給大家看一下eclipse中生成的伺服器端程式:

這裡寫圖片描述

注意將下載之後的cxf的3.1.8版本lib裡的所有jar包都拷貝到專案中,並建立引用關係,筆者這裡就是上圖“Libraries”中的“WebServiceServer”庫。

1.1.2 建立pojo

先寫一個pojo,即檔案Person.java

package com.yhd.webservice.cxf.server.poto;

/**
 * 類名稱:Persion.java<br>
 * 類描述:<br>
 * 建立時間:2016年11月11日, 下午2:48:45
 * 
 * @version
1.0 * @since JDK1.7.0_65 * @author yhd */
public class Person { private String name; private int age; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public
void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }

1.1.3 建立介面

定義一個介面,即檔案PersonService.java

package com.yhd.webservice.cxf.server.service;

import java.util.List;

import javax.jws.WebParam;
import javax.jws.WebService;

import com.yhd.webservice.cxf.server.poto.Person;

/**
 * 類名稱:PersonService.java<br>
 * 類描述:<br>
 * 建立時間:2016年11月11日, 下午2:43:36
 * 
 * @version 1.0 
 * @since JDK1.7.0_65
 * @author yhd
 */

@WebService
public interface PersonService {

        public List<Person> findAll(@WebParam(name = "arg0") String name); 

}

1.1.4 介面實現類

介面類的實現,即檔案PersonServiceImp.java

package com.yhd.webservice.cxf.server.service.impl;

import java.util.ArrayList;
import java.util.List;

import javax.jws.WebService;

import com.yhd.webservice.cxf.server.poto.Person;
import com.yhd.webservice.cxf.server.service.PersonService;

/**
 * 類名稱:PersonServiceImp.java<br>
 * 類描述:<br>
 * 建立時間:2016年11月11日, 下午2:47:53
 * 
 * @version 1.0 
 * @since JDK1.7.0_65
 * @author yhd
 */

@WebService(endpointInterface="com.yhd.webservice.cxf.server.service.PersonService",serviceName="person")
public class PersonServiceImp implements PersonService {

    @Override
    public List<Person> findAll(String name){  
        ArrayList<Person> persons = new ArrayList<Person>();  

        Person p1 = new Person();
        p1.setName(name + "3");
        p1.setAge(18);

        Person p2 = new Person();
        p2.setName(name + "4");
        p2.setAge(20);

        persons.add(p1);
        persons.add(p2);

        return persons;  
    }  
}

1.1.5 spring配置檔案application-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<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-2.5.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"
    xmlns="http://www.springframework.org/schema/beans">

    <bean id="jaxWsServiceFactoryBean" class="org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean">
        <property name="wrapped" value="true" />
    </bean>

    <jaxws:endpoint id="serviceimp" address="/person"
        implementor="com.yhd.webservice.cxf.server.service.impl.PersonServiceImp">

        <jaxws:serviceFactory>
            <ref bean="jaxWsServiceFactoryBean" />
        </jaxws:serviceFactory>
    </jaxws:endpoint>
</beans>

這裡要注意,網上很多配置cxf的參考文章都提到要將三個配置資訊放到spring的配置檔案中:

<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" />

但是對於這裡使用到的cxf最新版3.1.8,如果加上:

<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />

反而會報錯:

嚴重: Context initialization failed
org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Failed to import bean definitions from URL location [classpath:META-INF/cxf/cxf-extension-soap.xml]

網上說cxf3.0之後可能已經不需要這個檔案了,將這個檔案去掉就可以了。或者將這三個配置都去掉也可以。筆者將這三者都去掉了,可以使用。

1.1.6 配置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" 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">
  <display-name>WebServiceServer</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>

  <display-name>cxfTest</display-name>  
    <context-param>  
        <param-name>contextConfigLocation</param-name>  
        <param-value>/WEB-INF/application-context.xml</param-value>  
    </context-param>  
    <listener>  
        <listener-class>  
            org.springframework.web.context.ContextLoaderListener     
        </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>/hello/*</url-pattern>  
    </servlet-mapping>

</web-app>

這裡面配置了spring的監聽器,又配置了一個cxf的servlet。

1.2 啟動web工程

筆者這裡在tomcat中配置了web工程的埠號為8081,並且將8081直接指向eclipse中工程的地址,所以訪問該工程時就不用再輸入工程名了。

啟動tomcat。在瀏覽器裡輸入:

如上所示,沒有再輸入工程名“WebServiceServer”。

這時瀏覽器頁面會出現:

這裡寫圖片描述

能看到“person”前有一個倒過來的類包的名稱。

這說明伺服器端已經建立成功!

2 生成伺服器端介面類

2.1 安裝cxf

cxf官網下載cxf的3.1.8版本,筆者下載的zip版。將檔案解壓縮並放到一個合適的目錄下。在環境變數中加入變數“CXF_HOME”,值就是安裝路徑;再在“PATH”變數中加入:

%CXF_HOME%\bin

這樣cxf的命令就可以使用了。

2.2 使用“wsdl2java”命令生成介面類

wsdl2java的用法如下:

wsdl2java –p 包名 –d 目錄名 wsdl路徑

具體的意義如下:

  • -p:指定其wsdl的名稱空間,也就是要生成程式碼的包名

  • -d:指定要產生程式碼所在目錄

  • -client 生成客戶端測試web service的程式碼

  • -server:生成伺服器啟動web service的程式碼

  • -impl:生成web service的實現程式碼

  • -ant:生成build.xml檔案

  • -compile:生成程式碼後編譯

  • -quient:靜默模式,不輸出警告與錯誤資訊

  • -all:生成所有開始端點程式碼:types,service proxy,service interface, server mainline, client mainline, implementation object, and an Ant build.xml file.

筆者這裡的命令為:

wsdl2java -p com.yhd.webservice.cxf.client.info -d D:\test http://localhost:8081/hello/person?wsdl

執行之後就會在-d後面的路徑下生成相應的類。

2.3 將介面類拷貝到客戶端專案中

將這些類拷貝到後面新建立的客戶端專案中。

有的時候生成了類之後,將這些類拷貝到客戶端專案,類中的某些super()會報錯。這就需要再加上“-frontend jaxws21”命令,也就是將命令寫為:

wsdl2java -frontend jaxws21 -p com.yhd.webservice.cxf.client.info -d D:\test http://localhost:8081/hello/person?wsdl

再生成的類就不會報錯了。

3 建立客戶端程式

客戶端我們就做一個簡單的程式。

依然建立一個web專案(其實建立一個java專案就可以了),依賴的類與伺服器端一樣,將cxf的jar包都拷貝進去,程式如下:

這裡寫圖片描述

將伺服器端生成的介面類拷貝過來,然後再建立一個“ClientTest.jar”檔案,內容如下:

package com.yhd.webservice.cxf.client.main;

import java.util.List;

import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

import com.yhd.webservice.cxf.client.info.Person;
import com.yhd.webservice.cxf.client.info.PersonService;

/**
 * 類名稱:ClientTest.java<br>
 * 類描述:<br>
 * 建立時間:2016年11月15日, 上午10:04:16
 * 
 * @version 1.0 
 * @since JDK1.7.0_65
 * @author yhd
 */

public class ClientTest {

    public static void main(String[] args) {

        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        factory.setServiceClass(PersonService.class);
        factory.setAddress("http://localhost:8081/hello/person");
        PersonService service = (PersonService)factory.create();
        List<Person> list = (List<Person>)service.findAll("張");

        for(Person person : list) {
            System.out.println("name=" + person.getName());
            System.out.println("age=" + person.getAge());
            System.out.println("-------------------");
        }
    }

}

4 執行客戶端程式

在伺服器端保持執行的狀態下,執行客戶端程式。正常的話,會打印出:

name=張3
age=18
-------------------
name=張4
age=20
-------------------

有一點要注意,一方面,一定要保持客戶端和伺服器端使用的jdk版本是一致的,另一方面,cxf從3.1開始已經不支援jdk的1.6版本了,而至少是jdk的1.7或者是以上的版本。所以我們的專案裡的jdk至少需要使用jdk的1.7版本,否則比如使用1.6,有可能會報錯:

Caused by: java.lang.UnsupportedClassVersionError: org/apache/cxf/jaxws/spring/NamespaceHandler : Unsupported major.minor version 51.0
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(Unknown Source)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access000(UnknownSource)atjava.net.URLClassLoader1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:1191)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1669)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1547)
at org.springframework.util.ClassUtils.forName(ClassUtils.java:266)
at org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver.resolve(DefaultNamespaceHandlerResolver.java:124)

這一點大家要注意。

5 關於附件原始碼

文章中伺服器端程式和客戶端程式的原始碼都放在了筆者github的網站裡面,其中:

伺服器端程式位於:

客戶端程式位於: