使用XFire开发webservice服务和客户端全攻略

本文介绍了如何使用XFire和Spring集成开发Web Service应用,包括XFire的特点、与Axis的性能对比,以及详细的开发步骤。通过配置web.xml、实现接口和服务类,以及Spring的配置文件,展示了创建一个简单Web Service的过程。文章还提供了基于XFire的复杂示例,涉及用户管理的业务逻辑和数据对象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 
XFire是与Axis 2并列的新一代Web Service框架,通过提供简单的API支持Web Service各项标准协议,帮助你方便快速地开发Web Service应用。

相 对于Axis来说,目前XFire相对受欢迎,加上其提供了和Spring集成的支持,在目前的Web Service开源社区拥有众多的追随者。并且因为XFire为Spring提供的支持,使得我们可以很容易在Spring中使用XFire构建Web Service应用。

XFire与Axis2相比具有如下特征:

l         支持一系列Web Service的新标准--JSR181、WSDL2.0 、JAXB2、WS-Security等;

l         使用Stax解释XML,性能有了质的提高。XFire采用Woodstox 作Stax实现;

l         容易上手,可以方便快速地从pojo发布服务;

l         支持Spring、Pico、Plexus、Loom等容器;

l         灵活的Binding机制,包括默认的Aegis,xmlbeans,jaxb2,castor;

l         高性能的SOAP 栈设计;

l         支持Spring、Pico、Plexus、Loom等容器。

XFire与Axis1性能的比较如下:

l         XFire比Axis1.3快2-6倍;

l         XFire的响应时间是Axis1.3的1/2到1/5。

XFire在WebService框架中开始较晚,它从现有的框架中借鉴了许多优秀的理念,力争将Web Service的应用开发难度降到最低。此外,还提供了各种绑定技术、支持多种传输协议,对WebService体系中许多新的规范提供了支持。

下面让我们来看一个XFire于Spring集成的helloWorld的简单例子。

一.实现的功能和特点

    本例具有如下功能和特点:

1) 基于J2EE平台的Web Service服务;

2) 开发方便,配置简单;

3) 与spring无缝集成。

XFire是完全基于流数据处理进行工作的系统,这意味着XFire不是将整个SOAP文档缓存在内存中,而是以管道的方式接收SOAP流数据。这种工作方式的转变带来了可观的性能回报,同时节省了内存的占用。

  XFire从 管道中接收一个SOAP请求到返回一个SOAP响应,会经历一系列的阶段。在管道调用的任何一个阶段,XFire都可以添加一些额外的Handler,在 对消息进行加工处理后再传入到下一个阶段中。在SOAP请求消息对Web Service发起真正调用之前,分别会经过传输、预转发、转发、策略实施、用户信息处理、预调用、服务调用等阶段。

二.开发环境

    笔者的开发环境描述如下:

1) jdk: 1.5版本;

2) Tomcat:5.5.20;

3) MyEclipse:5.1.1 GA。

三.开发步骤

1. 工程与环境的建立

在 MyEclipse中新建Web工程,名为webservice_helloworld。选择该工程后,点击右键选择MyEclipse->Add Web Service Capabilities,弹出Add Web Service Capabilities对话框,点击“Next”,弹出Project Library Configuration对话框,默认选择Core Libraries,点击“Finish”按钮,完成XFire核心包的添加。为了后续的客户端的测试,还需读者加入commons- httpclient.jar包到WEB-INF/lib下。

部署后可看到此时WEB-INF/lib的jar包列表如下:

activation-1.1.jar、 commons-beanutils-1.7.0.jar、commons-codec-1.3.jar、commons- httpclient.jar、commons-logging-1.0.4.jar、jaxen-1.1-beta-9.jar、jaxws-api- 2.0.jar、jdom-1.0.jar、jsr173_api-1.0.jar、mail-1.4.jar、saaj-api-1.3.jar、 saaj-impl-1.3.jar、spring-1.2.6.jar、stax-api-1.0.1.jar、wsdl4j-1.5.2.jar、 wstx-asl-3.0.1.jar、xbean-2.1.0.jar、xbean-spring-2.5.jar、xfire-aegis- 1.2.2.jar、xfire-annotations-1.2.2.jar、xfire-core-1.2.2.jar、xfire- java5-1.2.2.jar、xfire-jaxws-1.2.2.jar、xfire-jsr181-api-1.0-M1.jar、xfire- spring-1.2.2.jar、XmlSchema-1.1.jar

为了后续的开发和测试,在src目录下分别建立test和webservice目录,分别用于存放测试文件和webservice的相关类。

2.Web Service实现的编写

    在本例中,我们只是做一个helloWorld的简单例子。Web Service服务端提供一个根据输入的名字信息回复相应的helloWorld信息的。例如,当名字为“阿蜜果”时,恢复信息为“hello,阿蜜果”。下面让我们一步一步来开始进行编码。

1)web.xml的配置

一 般情况下,我们通过HTTP作为Web Service的传输协议,这样我们只需启动一个Web服务器(如Tomcat,在本例中使用的是Tomcat5.5.20),这样客户端就可以通过 HTTP访问到Web Service服务。为了集成Spring容器,XFire专门提供一个XFireSpringServlet,我们可以在web.xml中配置该 Servlet,将Spring容器中定义的Web Service在某个URI下发布。

为了能正确使用XFire,需在web.xml中进行相应配置,在该文件中配置XFire的servlet和servlet-mapping。同时因为本实例需要将XFire集成到Spring中,因而需要在web.xml文件中加载Spring的相应配置文件。在本实例中,我们首先在WEB-INF下建立两个配置Spring配置文件,一个为applicationContext.xml,该文件用来定义本工程的bean,一个为xfire-servlet.xml,用来配置XFire的相关bean。修改后的web.xml的内容如下所示

<?xml version="1.0" encoding="UTF-8"?>
web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.4" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee   http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
   <display-name>XFireService</display-name>
   <!-- begin Spring配置 -->
    <context-param>
       <param-name>contextConfigLocation</param-name>
       <param-value>/WEB-INF/applicationContext.xml,/WEB-INF/xfire-servlet.xml</param-value>
    </context-param>
    <listener>
       <listener-class> org.springframework.web.context.ContextLoaderListener
       </listener-class>
    </listener>
     <listener>
       <listener-class>     org.springframework.web.util.IntrospectorCleanupListener
       </listener-class>
    </listener>
    <!-- end Spring配置 -->
    <!-- begin XFire 配置 -->
   <servlet>  
      <servlet-name>xfire</servlet-name>  
       <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    </servlet>  
    <servlet-mapping>
      <servlet-name>xfire</servlet-name>
      <url-pattern>*.ws</url-pattern>
   </servlet-mapping>
    <servlet>
      <!-- 配合Spring容器中XFire一起工作的Servlet-->
       <servlet-name>xfireServlet</servlet-name>
       <servlet-class>org.codehaus.xfire.spring.XFireSpringServlet</servlet-class>
    </servlet>
    <servlet-mapping>
       <servlet-name>xfireServlet</servlet-name>
       <!-- 在这个URI下开放Web Service服务 -->
       <url-pattern>/service/*</url-pattern>
   </servlet-mapping>
   <!-- end XFire 配置 -->
</web-app>


    2)Web Service的接口类HelloWorld.java和对应实现类HelloWorldImpl.java

为了用Web Service完成HelloWorld功能,我们首先在src/webservice目录下建立接口类HelloWold.java。它仅包含一个sayHelloWorld(String name)的方法,其详细内容如下:

package webservice;
publicinterface HelloWorld {
  
    String sayHelloWorld(String name);
}
我们还需要建立一个对应的实现类,来实现sayHelloWorld的功能,该实现类即为HelloWorldImpl.java。该类的详细内容如下:
package webservice;
 /** *//**
 *HelloWorld的实现类.
 */
 publicclass HelloWorldImpl implements HelloWorld  {
     public String sayHelloWorld(String name)  {
       String helloWorld = "hello," + name;
       return helloWorld;
    }
}


3)Spring配置文件applicationContext.xml和xfire-servlet.xml的配置

首先我们在applicationContext.xml文件中配置对应的bean——HelloWorldBean,该xml文件的内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <bean id="HelloWorldBean" class="webservice.HelloWorldImpl"/>
</beans>

     这个配置文件很简单,在此不详述。

XFire为 Spring提供了方便易用的导出器XFireExporter,借助该导出器的支持,我们可以在Spring容器中将一个POJO导出为Web Service。HelloWorld是业务服务类,在此拥有一个sayHelloWorld的方法,我们希望将此方法开放为Web Service。在实际应用中,如果某个类具有众多的方法,而其中的某些方法不需要开放为Web Service的情况下,我们可以定义一个窄接口,该接口中只需定义那些开放为Web Service的业务方法。

将一个业务类所有需要开放为Web Service的方法通过一个窄接口来描述是值得推荐的作法,这让Web Service的接口显得很“干净”。其次,XFire的导出器也需要服务接口的支持,因为它采用基于接口的动态代理技术。

窄接口中的方法在真实的系统中可能需要引用其它的业务类或DAO获取数据库中的真实数据,为了简化实例,我们在此简化了实例。

下面让我们看看在xfire-servlet.xml文件中导出器的设置,该文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <!-- 引入XFire预配置信息 -->
    <import resource="classpath:org/codehaus/xfire/spring/xfire.xml" />
    <!—定义访问的url-->
    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
       <property name="urlMap">            
           <map>                
              <entry key="/HelloWorldService.ws">                 
                  <ref bean="HelloWorldService" />                
              </entry>            
           </map>        
       </property>    
    </bean>    

    <!-- 使用XFire导出器 -->
    <bean id="baseWebService" class="org.codehaus.xfire.spring.remoting.XFireExporter" lazy-init="false" abstract="true">
       <!-- 引用xfire.xml中定义的工厂 -->
       <property name="serviceFactory" ref="xfire.serviceFactory" />
       <!-- 引用xfire.xml中的xfire实例 -->
       <property name="xfire" ref="xfire" />
    </bean>
    <bean id="HelloWorldService" parent="baseWebService">
       <!-- 业务服务bean -->
       <property name="serviceBean" ref="HelloWorldBean" />
       <!-- 业务服务bean的窄接口类 -->
       <property name="serviceClass" value="webservice.HelloWorld" />
    </bean>
</beans>


在 上面的配置中,我们可以看到,在该配置文件中引入了xfire.xml这个Spring配置文件。它是在XFire核心JAR包中拥有一个预定义的 Spring配置文件,它定义了XFire在Spring中必须用到的一些Bean和资源,需要引入这个预定义的配置文件。从该配置文件中可以看出,我们通过XFireExporter将业务类导出为Web Service,对于任何导出器,我们都需要引入XFire环境,即serviceFactory和xfire,这是标准的配置。ServiceFactory是XFire的核心类,它可以将一个POJO生成为一个Web Service。

在本实例中,我们通过定义一个baseWebService,其余的webService配置都将该bean作为父bean,这样可以简化Spring的配置,不需要多次引入serviceFactory和xfire

 

实际的应用过程中,遇到的情况比这个要复杂得多,例如,传入参数是对象、返回自定义对象、返回数组、返回列表。下面让我们在此文中对XFire+Spring进行更深层的探讨吧。

一.             本例概述

在本例中,我们将在业务逻辑类是一个用户的业务逻辑类,包括创建用户、获取单个用户、获取用户数组、获取用户列表四个方法,因该文讲的是XFire+Spring构建webservice,所以在该例中我们并不涉及具体的数据库操作,而只是提供模拟实现。方法描述如下:

1) 创建用户方法:createUser(User user)

通过传入User对象作为参数来才创建用户;

2) 通过用户名获取用户信息方法:getUser(String loginName)

根据用户名获取某用户对象,该方法返回的是一个User对象;

3) 返回所有用户的数组方法:getUserArray()

返回为User数组;

4) 返回所有用户的列表的方法:getUserList()

返回为List对象,放入的对象为User类型。

二.             数据对象User.java

在上篇的例子中,src/webservice目录下新建example2目录,并在example2目录下建立User.java文件,下面看看数据对象User.java的内容,代码如下:

package webservice.example2;

import java.util.Date;

 /** *//**
 *用户对象. 
 *@author<a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
 *@version1.0
 *Creationdate:2007-9-28-上午10:42:44
 */
 publicclass User implements java.io.Serializable  {
    private static final long  serialVersionUID = 1L;

     /** *//**用户名*/
    private String loginName;

     /** *//**用户密码*/
    private String password;

     /** *//**手机号*/
    private String mobile;

     /** *//**创建时间*/
    private Date createTime;

     public Date getCreateTime()  {
       return createTime;
    }

     public void setCreateTime(Date createTime)  {
       this.createTime = createTime;
    }

     public String getLoginName()  {
       return loginName;
    }

     public void setLoginName(String loginName)  {
       this.loginName = loginName;
    }

     public String getMobile()  {
       return mobile;
    }

     public void setMobile(String mobile)  {
       this.mobile = mobile;

    }

     public String getPassword()  {
       return password;
    }

     public void setPassword(String password)  {
       this.password = password;
    }

     public String toString()  {
       StringBuffer sb = new StringBuffer();
       sb.append("loginName=" + this.loginName);
       sb.append("|password=" + this.password);
       sb.append("|mobile=" + this.mobile);
       sb.append("|createDate=" + this.createTime);
       return sb.toString();
    }
}


 

三.             用户业务类UserService.java及其实现UserServiceImpl.java

下面让我们来看看本例的业务逻辑接口类UserService.java的内容:

package webservice.example2;

import java.util.List;

 /** *//**
 *用户业务类.
 *@author<a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
 *@version1.0
 *Creationdate:2007-9-28-上午10:37:09
 */
 public interface UserService  {
     /** *//**
     *获取用户对象.
     *@paramloginName用户名
     *@return返回用户对象
     */
    public User getUser(String loginName);

     /** *//**
     *创建用户.
     *@paramuser用户对象
     *@return返回创建的对象的toString()方法返回的内容
     */
    public String createUser(User user);

     /** *//**
     *获取用户信息数组.
     *@return返回用户信息数组
     */
    public User[] getUserArray();
   
     /** *//**
     *获得用户信息列表.
     *@return返回用户信息列表
     *@author<a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
     *Creationdate:2007-9-28-下午12:55:37
     */
    public List<User> getUserList();
}

 

它的实现类UserServiceImpl.java的内容如下:

package webservice.example2;

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

 /** *//**
 *用户业务实现类.
 *@author<a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
 *@version1.0
 *Creationdate:2007-9-28-上午10:54:11
 */
 publicclass UserServiceImpl implements UserService  {
     /** *//**
     *获取用户对象.
     *@paramloginName用户名
     *@return返回用户对象
     */
     public User getUser(String loginName)  {
       User user = new User();
       user.setLoginName(loginName);
       user.setPassword("12345678");
       user.setMobile("13812345678");
       user.setCreateTime(new Date());
       return user;
    }

     /** *//**
     *创建用户.
     *@paramuser用户对象
     *@return返回创建的对象的toString()方法返回的内容
     */
     public String createUser(User user)  {
       user.setCreateTime(new Date());
       return user.toString();
    }

     /** *//**
     *获取用户信息数组.
     *@return返回用户信息数组
     */
     public User[] getUserArray()  {
       User[] userList = new User[4];
       userList[0] = getUser("阿蜜果");
       userList[1] = getUser("sterning");
       userList[2] = getUser("娟子");
       userList[3] = getUser("老肖");
       return userList;
    }

     /** *//**
     *获得用户信息列表.
     *@return返回用户信息列表
     *@author<a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
     *Creationdate:2007-9-28-下午12:55:37
     */
     public List<User> getUserList()  {
       List<User> userList = new ArrayList<User>();
       userList.add(getUser("阿蜜果"));
       userList.add(getUser("sterning"));
       userList.add(getUser("娟子"));
       userList.add(getUser("老肖"));
       return userList;
    }
}

注意:getUserList()方法返回的List中需要采用泛型,不然会部署失败。

到此为止,我们的业务已经完成,剩下的工作只是修改配置文件和编写测试类来进行测试。让我们继续往下走吧。

四.             配置文件applicationContext.xml和xfire-servlet.xml的修改

在本小节中,我们需要修改配置文件。首先在applicationContext.xml文件中添加用户逻辑bean的定义,添加的代码如下:

<bean id="UserBean" class="webservice.example2.UserServiceImpl"/>

接下来我们还需要修改xfire-servlet.xml文件来暴露我们的Web Service,修改后的该文件内容如下所示:

<entry key="/UserService.ws">                    

<ref bean="UserService" />                

</entry>

并添加如下bean的定义:

<bean id="UserService" parent="baseWebService">
       <!-- 业务服务bean -->
       <property name="serviceBean" ref="UserBean" />
       <!-- 业务服务bean的窄接口类 -->
       <property name="serviceClass" value="webservice.example2.UserService" />
    </bean>

   我们的Web Service已经开发完成,启动本项目后,可通过浏览器访问:http://localhost:8080/webservice_helloworld/UserService.ws?wsdl,我们可以在浏览器中看到该例的WSDL信息。

 

 

 

最后,我们来用xfire的eclipse客户端代码生成插件来生成webservice的客户端调用代码


To install the Eclipse XFire plugin:

go to the Help menu, select "Software Updates" and then select "Find and Install."
Select "Search for new features to install" and click Next.
Select "Create New Remote Site" and enter "XFire" as the name and http://dist.codehaus.org/xfire/update/ as the eclipse update site.
Select OK.
Select Finish
Using the Plugin

The first step is to start the code generation wizard. Go to File->New->Other. Then select Code generation from WSDL document.

 
The plugin will then prompt you for the location of your WSDL, where to output the code, and also what package you would like the service in.
 

 
Once you're done you'll see the generated classes in your IDE!

 

 

 

 


不要加myeclipse中的XFire库文件,因为客户端运行所导入的xfire1.2.6和服务器端的xfire1.2.5版本不一致,导致以上问题。

直接下载xfire-1.2.6,把其中的lib加到project就好了。

4.最后写个测试程序就好。

import com.kuaff.xfire.samples.MathServiceClient;

import com.kuaff.xfire.samples.MathServicePortType;

 

public class Test {

    public static void main(String[] args) {

       MathServiceClient client = new MathServiceClient();

       MathServicePortType MathService = client.getMathServiceHttpPort();

       // 调用服务

       long result = MathService.add(1, 2);

       System.out.println("结果:" + result);

    }

}

 

当有参数传递时,

import test.HelloServiceClient;

import test.HelloServicePortType;

import test.ObjectFactory;

import test.User;

import javax.xml.namespace.QName;

 

 

 

 

public class TestAddress {

    public static void main(String[] args) {

       HelloServiceClient client = new HelloServiceClient();

       HelloServicePortType HelloService = client.getHelloServiceHttpPort();

      

//     当要传递参数时,调用ObjectFactory中的公用方法,而不用自己还要

       //new JAXBElement<String>(new

//     QName("http://test", "username"),String.class,"dfdfs");

       //直接调用factory.createUserUsername("dfdfs")返回JAXBElement<String>类型

      

       ObjectFactory  factory=new ObjectFactory();

       User user=factory.createUser();

       user.setPassword(factory.createUserPassword("afdsafsd"));

       user.setUsername(factory.createUserUsername("dfdfs"));

      

       // 调用服务

       //由JAXBElement转化为String,调用getValue();

       System.out.println(HelloService.getUser(user).getUsername().getValue());

    }

}

 

 

 

 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值