搭建基于CXF的WebService服务器及其应用

来源:互联网 发布:淘宝汽车拥品 编辑:程序博客网 时间:2024/05/20 08:24

因为即将在项目中使用到web service,所以,我提前学习了下这个东西。

不看不知道,一看吓一跳。

好久以前学习并使用过的XFire竟然已经和Celtix合并成了CXF,还出了几个版本。

看来,人还是需要经常关注技术发展的,否则,还真是要掉队了。

(废话太多了?那好吧,我开始演示我的小实验。)

 

首先,下载CXF,官网(http://cxf.apache.org/ ),解压后,得到以下目录。

         其中,lib为jar包,在接下来的工作中需要用到。

 

下面,我们开始建立工程。

一、组建提供WebService的服务器端项目。

     1. 在eclipse/myEclipse中建立web工程cxf2,将CXF_HOME/lib下的所有jar复制到工程的lib中,并添加到buildpath中。

     2. 新建一个新POJO,为User.Java。

package server;

public class User {
    String first;
    String last;
    public String getFirst() {
    return first;
    }
    public void setFirst(String first) {
    this.first = first;
    }
    public String getLast() {
    return last;
    }
    public void setLast(String last) {
    this.last = last;
    }
}

 

     3. 因为CXF提供的所有webservice都基于接口,所以,新建一个接口UserService。如下:

package server;

import javax.jws.WebService;

@WebService
public interface UserService {
    
    void add(User user);
    
    User[] findAllUsers();
}

其中,@WebService注解是CXF必须的,照搬吧。

 

    4. 新建一个类UserServiceImpl.java,并实现接口UserService。如下:

package server;

import java.util.List;
import java.util.Vector;

import javax.jws.WebService;

import org.apache.log4j.Logger;

@WebService(endpointInterface = "server.UserService",serviceName = "UserService",portName="UserServicePort")
public class UserServiceImpl implements UserService {
    static List<User> UserRepository= new Vector<User>();
    private static Logger log = Logger.getLogger(UserServiceImpl.class);
    {
        log.info("CXF正在初始化 UserServiceImpl.");
    }
    public void add(User user) {
        log.info("CXF正在添加一个用户: "+user.getFirst()+"."+user.getLast());
        UserRepository.add(user);
    }
    
    public User[] findAllUsers() {
        User[] users= new User[UserRepository.size()];
        UserRepository.toArray(users);
        return users;
    }
}

这里,注解@WebService(endpointInterface = "server.UserService",serviceName = "UserService",portName="UserServicePort")与上面不一样,可以省略。

但在复杂的应用中,不能省略,如指定哪些方法可供远程调用时,需要用到注解。(个人愚见)

 

5.配置web.xml。

(1)在web.xml中添加CXF的配置文件定义。

<context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>WEB-INF/beans.xml</param-value>
 </context-param>

(2)在web.xml中添加如下监听器和servlet。

<!-- 因为CXF3.0依赖于spring,需要添加这个listener-->
    <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>/webServices/*</url-pattern>
    </servlet-mapping>

6.建立CXF的配置文件,存放路径要与web.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.xsd
        http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

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

    <jaxws:endpoint id="userService" implementor="server.UserServiceImpl" address="/userService" />

</beans>

 

经过上面步骤,我们已经完成配置了一个提供webservice的服务器。

启动tomcat,在浏览器中输入地址:http://localhost:8880/cxf2/webServices/userService,将返回一个wsdl文件(xml)。

(如果是IE,需要查看源文件来查看。如果是firefox,可以直接看到xml代码。)

更详细的访问地址为:http://localhost:8880/cxf2/webServices/userService?wsdl。

 

工程目录如图:

 

二、上面,我们已经成功配置了一个webservice服务器。接下来,我们建立另一个工程来模拟远程调用webservice。

1.新建一个工程testCxf,将上面服务器工程中的User.java和UserService.java复制到工程testCxf中。

2.新建一个类Client.java,代码如下:

package server;

import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

public class Client {
    public static void main(String[] arg){

        JaxWsProxyFactoryBean soapFactoryBean = new JaxWsProxyFactoryBean();
        soapFactoryBean.setAddress("http://localhost:8880/cxf2/webServices/userService");    // 这个就是第一个工程完成后所测试的地址。
        soapFactoryBean.setServiceClass(UserService.class);
        Object o = soapFactoryBean.create();
        UserService userService = (UserService) o;
        User user= new User();
        user.setFirst("James");
        user.setLast("Bond");
        userService.add(user);
        User[] users= userService.findAllUsers();
        for(User u : users){
            System.out.println(u.getFirst()+"."+u.getLast());
        }
    }
}

 

执行这个java类,我们会看到控制台输出了相应信息。

CXF正在添加一个用户: James.Bond                (这个信息为第一个工程输出)

James.Bond                                                  (这个信息为第二个工程输出)

如果运行多次,在最后一次运行后,将会看到有多个“James.Bond ”被输出。

由此,我们可以看到,服务器所提供的webservice已经被成功调用。

到此,两者的通信已经建立,你想做什么就做什么吧,尽情发挥你天马行空的创意。

 

工程目录如图:

 

 

需要两个工程的朋友,可以从这里下载。

http://download.csdn.net/source/2775877 (服务器端)

http://download.csdn.net/source/2775884 (客户端)

 

 

后记:

三、由于我们通常不知道提供Web Service的服务器接口及其相关类的代码,我们也不可能从他人那里获得。

对此,CXF提供了一些命令行工具,在CXF_HOME/bin下。

使用wsdl2java,可以根据从服务器返回的wsdl文件生成我们所需要的java接口和相关类。

在上面的工程中,我们可以用以下命令生成JAVA代码,而不是从第一个工程中复制过来。

wsdl2java -p client http://localhost:8880/cxf2/webServices/userService?wsdl         (需要在cmd窗口中将路径切换至CXF_HOME/bin下)

(解释:wsdljava    –p    包路径    –d    目标文件夹   wsdl 的url地址)


四、需要注意的是,对于接口类和相关类的包路径,一定要和服务器的一样,(可以通过第三个步骤知道包路径)

否则,会出现Unexpected wrapper element {****}addResponse found.……错误。

 

原创粉丝点击