【技术分享】在java中使用spring整合cxf实现webservice

2016年11月21日 345点热度 0人点赞 0条评论

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。在浏览器里输入:

http://localhost:8081/hello

如上所示,没有再输入工程名“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=张3age=18
-------------------
name=张4age=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的网站里面,其中:

服务器端程序位于:

https://github.com/yuhaidong/WebServiceServer

客户端程序位于:

https://github.com/yuhaidong/WebServiceClient

文章来源:飞利信软件中心于海东

图片

5330【技术分享】在java中使用spring整合cxf实现webservice

root

这个人很懒,什么都没留下

文章评论