微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

webService---使用Xfire从WSDL生成客户端详

 转自:http://blog.csdn.net/stoneyang2005/archive/2009/02/26/3939117.aspx

如果多家供应商为一家用户做Web项目时,往往会用到WebService来进行数据的同步,比如用户同步。若远程调用后返回的值并不是字符串(内容是xml格式),而是供应商甲程序中的实体(如User对象),那么供应商乙若要调用供应商甲提供的WebService接口,可以:

1、  将供应商甲的源代码,拷贝过来使用;

2、  将供应商甲相关的源代码的class文件打成jar包,拷贝过来使用;

 

看似两种方式都可以,但是,由于供应商甲开发的目录结构很混乱以致于不方便找寻所有相关的源码或打成jar包;或你认为他们的目录结构很繁冗或你没有足够的时间和对方进行交流来部署自己的环境;或双方公司之间竞争激烈,网络不安全等因素不允许相互传送代码,或由于日后WebService公布的接口越多造成更多的同样的问题……

为了解决这个问题,可以使用XFire的Wsgen从动态的WSDL中生成客户端较为方便。

 

请下载ANT包供环境使用 :

ANT下载地址为http://www.apache.org/dist/ant/binaries/apache-ant-1.7.1-bin.zip

 

一、ANT的配置

1、下载apache-ant-1.7.1-bin.zip,并解压缩到某一目录,在环境变量中添加ANT_HOME,值为安装目录;

2、把%ANT_HOME%/bin;添加到path环境变量中,在命令行下运行 ant -version,若有输出,比如“Apache Ant version …… compiled on …… ”,则说明配置成功。

 

二、通过WSDL生成客户端

1、      新建一个Java工程,取名为XFireWsgen,向IDE中导入相关依赖的jar包, “http://blog.csdn.net/stoneyang2005/archive/2009/02/24/3931841.aspx”的“一、1”中有说明;

2、      如图1,创建相应的文件夹和xml文件

    

创建xml

     图1

 

XFireWsgen: 创建xfire文件

XFireWsgen/xfire: 创建WsGen文件

XFireWsgen/xfire/WsGen:创建client文件夹、lib文件夹、build.xml文件

XFireWsgen/xfire/WsGen/client:存放的是生成的客户端代码,需在build.xml文件中进行配置

XFireWsgen/xfire/WsGen/lib:存放的是上面所述依赖的jar包,并且需在build.xml文件中进行配置

XFireWsgen/xfire/WsGen/build.xml 根据此文件,通过ANT出客户端

 

build.xml

       view plaincopy to clipboardprint?
<project name="XFire-WsGen" basedir="./WsGen" default="wsgen"> 
 
     <path id="classpathId"> 
 
         <fileset file="${basedir}/lib/*.jar"> 
 
              <include name="*.jar"/> 
 
         </fileset> 
 
     </path> 
 
       
 
     <target name="clean" description="Prepare for clean build"> 
 
         <delete dir="${basedir}/client"/> 
 
         <mkdir dir="${basedir}/client"/> 
 
     </target> 
 
       
 
     <taskdef classpathref="classpathId" name="wsgen" classname="org.codehaus.xfire.gen.WsGenTask"></taskdef
 
   
 
     <target name="wsgen" depends="clean"> 
 
         <taskdef name='WsGenTask' classname="org.codehaus.xfire.gen.WsGenTask" classpathref="classpathId"/> 
 
         <WsGenTask outputDirectory="${basedir}/client" wsdl="http://localhost:38088/xfireDemo/services/business?wsdl" package="myclient" overwrite="true"/> 
 
     </target> 
 
</project> 
<project name="XFire-WsGen" basedir="./WsGen" default="wsgen">

     <path id="classpathId">

         <fileset file="${basedir}/lib/*.jar">

              <include name="*.jar"/>

         </fileset>

     </path>

    

     <target name="clean" description="Prepare for clean build">

         <delete dir="${basedir}/client"/>

         <mkdir dir="${basedir}/client"/>

     </target>

    

     <taskdef classpathref="classpathId" name="wsgen" classname="org.codehaus.xfire.gen.WsGenTask"></taskdef>

 

     <target name="wsgen" depends="clean">

         <taskdef name='WsGenTask' classname="org.codehaus.xfire.gen.WsGenTask" classpathref="classpathId"/>

         <WsGenTask outputDirectory="${basedir}/client" wsdl="http://localhost:38088/xfireDemo/services/business?wsdl" package="myclient" overwrite="true"/>

     </target>

</project>

 

 

其中,“${basedir}/lib/*.jar”的lib和 “${basedir}/client”的client,就是上面所说要配置的;“http://localhost:38088/xfireDemo/services/business?wsdl”就是供应商甲提供的WSDL的地址;“myclient”为客户端放置的包名。

 

3、      在浏览器输入wsdl(“http://localhost:38088/xfireDemo/services/business?wsdl”)保

证服务开启时,再使用ANT运行build.xml,可以从IDE中运行,刷新后client文件夹下将是生成的客户端代码,如图2所示

    

生成目录结构图

     图2

 

 

4、      拷贝client文件夹下的所有内容到 src目录下后并新建包 stoneyang.test和

Test.java类,如图3所示

   

拷贝客户端代码

    图3

 

Test为远程调用客户端,调用相关的接口:

Test.java

 view plaincopy to clipboardprint?
package stoneyang.test;  
 
import java.util.List;  
 
import javax.xml.bind.JAXBElement;  
 
import myclient.businessClient;  
import myclient.businessPortType;  
import stoneyang.bean.ArrayOfBook;  
import stoneyang.bean.Book;  
import stoneyang.businessi.arrayofstring;  
import stoneyang.businessi.GetBookByNameResponse;  
import stoneyang.businessi.GetBooksByNames;  
 
public class Test {  
    public static void main(String[] args){  
          
        businessClient rc = new businessClient();  
        businessPortType rpt = rc.getbusinessHttpPort();  
        //bean对象,集合产生的工厂  
        stoneyang.bean.ObjectFactory ofBookFactory = new stoneyang.bean.ObjectFactory();  
        //远程调用方法参数和返回值的工厂方法  
        stoneyang.businessi.ObjectFactory ofBusinessFactory = new stoneyang.businessi.ObjectFactory();  
          
        /*  第一个注释 
            QName qName = new QName("http://bean.stoneyang","year"); 
            JAXBElement<String> paramList = new JAXBElement<String>( qName,String.class,"1986"); 
        */ 
        //和下面的1行代码起到相同的作用,但是,下面的代码不需要再到Book.java或wsdl去找寻域名,成员变量名,显得更为方便  
        JAXBElement<String> yearJAXB = ofBookFactory.createBookYear("1986");  
          
        /*  第二个分注释 
            GetBookByNameResponse getBookByNameResult = ofBusinessFactory.createGetBookByNameResponse();  
            getBookByNameResult.setout(rpt.getBookByName("《小红帽》")); 
            Book book = getBookByNameResult.getout(); 
             
        */ 
        //和下面的1行代码起到相同的作用,但是下面的代码更为简洁,而且Java返回结果只有一种(要么String,要么List,而不会返回String和List)  
        Book book = rpt.getBookByName("《小红帽》");  
          
        book.setYear(yearJAXB);  
        println(book);  
          
          
        /*  第三个注释 
            arrayofstring bookNames = ofBusinessFactory.createarrayofstring(); 
            List<String> bookNameList = bookNames.getString(); 
            bookNameList.add("《社会心理学》"); 
            bookNameList.add("《心理学与生活》"); 
            ArrayOfBook books = rpt.getBooksByNames(bookNames); 
        */ 
        //和下面的7行代码起到相同的作用,虽然下面的代码看起来比较复杂,但是根据面向对象,使对象集中设置参数,集中取出参数,更方便维护,比如getBooksByNames有10个参数,那么这里只需要用getBooksByNamesPrama对象来取getIn0(),getIn1()……等  
        GetBooksByNames getBooksByNamesPrama = ofBusinessFactory.createGetBooksByNames();  
        arrayofstring bookNames = ofBusinessFactory.createarrayofstring();  
        List<String> bookNameList = bookNames.getString();  
        bookNameList.add("《社会心理学》");  
        bookNameList.add("《心理学与生活》");  
        getBooksByNamesPrama.setIn0(bookNames);  
        ArrayOfBook books = rpt.getBooksByNames(getBooksByNamesPrama.getIn0());//返回的结果可以和"第二个注释"一样,使用ofBusinessFactory.createGetBookByNameResponse()来创建返回结果  
          
        List<Book> listBook = books.getBook();  
        for( Book b: listBook ){  
            println(b);  
        }  
        ArrayOfBook booksWithSpecialYear = rpt.getBooksWithSpecialYear(book);//这里的参数类型和返回结果也可以使用ofBusinessFactory来创建,和上面的创建方式一样,这里为了看起来简单就这样写了。   
        List<Book> bookListWithSpecialYear = booksWithSpecialYear.getBook();  
        for( Book b: bookListWithSpecialYear ){  
            println(b);  
        }  
    }  
    public static void println(Book book){  
        String name = book.getName().getValue();  
        String author = book.getAuthor().getValue();  
        String year = book.getYear().getValue();  
        String price = book.getPrice().getValue();  
        StringBuilder builder = new StringBuilder();  
          
        if( name != null && !"".equals(name.trim())){  
            builder.append( " 名称: "+name );  
        }  
        if( author != null && !"".equals(author.trim())){  
            builder.append( " 作者: "+author );  
        }  
        if( year != null && !"".equals(year.trim())){  
            builder.append( " 年份: "+year );  
        }  
        if( price != null && !"".equals(price.trim())){  
            builder.append( " 价格: "+price );  
        }  
        System.out.println( builder.toString());  
    }  

package stoneyang.test;

import java.util.List;

import javax.xml.bind.JAXBElement;

import myclient.businessClient;
import myclient.businessPortType;
import stoneyang.bean.ArrayOfBook;
import stoneyang.bean.Book;
import stoneyang.businessi.arrayofstring;
import stoneyang.businessi.GetBookByNameResponse;
import stoneyang.businessi.GetBooksByNames;

public class Test {
 public static void main(String[] args){
  
  businessClient rc = new businessClient();
  businessPortType rpt = rc.getbusinessHttpPort();
  //bean对象,集合产生的工厂
  stoneyang.bean.ObjectFactory ofBookFactory = new stoneyang.bean.ObjectFactory();
  //远程调用方法参数和返回值的工厂方法
  stoneyang.businessi.ObjectFactory ofBusinessFactory = new stoneyang.businessi.ObjectFactory();
  
  /*  第一个注释
   QName qName = new QName("