【www.gdgbn.com--WebService】

上面的服务传递的是简单数据类型,返回的也是简单数据类型。下面我们用javabean 、list、map、array等返回值或参数完成webservice。

1、首先看看javabean模式的参数和返回值的webservice,javabean代码如下:

 

代码

package com.hoo.entity;

import java.io.serializable;

/**
 * function:user entity
 * @author hoojo
 * @createdate dec 16, 2010 10:20:02 pm
 * @file user.java
 * @package com.hoo.entity
 * @project axiswebservice
 * @blog http://blog.111cn.net/ibm_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
public class user implements serializable {
    private static final long serialversionuid = 677484458789332877l;
    private int id;
    private string name;
    private string email;
    private string address;
    //constractor
    //getter、setter

    @override
    public string tostring() {
        return this.id + "#" + this.name + "#" + this.email + "#" + this.address;
    }
}

 

没有上面特别就是一个普通的java对象,里面提供一些属性及getter、setter方法和tostring方法(在显示数据的时候有用),值得注意的是在远程调用的java对象都需要实现serializable接口,这样在网络中传递对象的时候就不会出现重复的javabean。用过或是了解ejb、rmi的朋友应该知道这点。序列化后的对象可以用io进行序列化写入到文件中,也可以反序列化解析到对象中的数据。

2、好,回正题。下面编写webservice的服务器端代码。

代码

package com.hoo.service;

import java.util.arraylist;
import java.util.date;
import java.util.hashmap;
import java.util.list;
import java.util.map;
import com.hoo.entity.user;

/**
 * function:axis webservice传递复杂类型数据
 * @author hoojo
 * @createdate dec 16, 2010 10:21:06 pm
 * @file manageruser.java
 * @package com.hoo.service
 * @project axiswebservice
 * @blog http://blog.111cn.net/ibm_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
@suppresswarnings("deprecation")
public class manageruser {
   
    public user getuserbyname(string name) {
        user user = new user();
        user.setid(new date().getseconds());
        user.setname(name);
        user.setaddress("china");
        user.setemail(name + "@hoo.com");
        return user;
    }
   
    public void setuser(user user) {
        system.out.println(user);
    }
   
    public list getusers(int i) {
        list users = new arraylist();
        for (int j = 0; j <= i; j++) {
            user user = new user();
            user.setid(new date().getseconds());
            user.setname("jack#" + j);
            user.setaddress("china");
            user.setemail("jack" + j + "@hoo.com");
            users.add(user);
        }
        return users;
    }
   
    public void setusermap(map maps教程) {
        system.out.println(maps);
    }
   
    public user[] getuserarray(int i) {
        user[] users = new user[i];
        for (int j = 0; j < i; j++) {
            user user = new user();
            user.setid(new date().getseconds());
            user.setname("jack#" + j);
            user.setaddress("china");
            user.setemail("jack" + j + "@hoo.com");
            users[j] = user;
        }
        return users;
    }
   
    public void setuserarray(user[] users) {
        for (user u : users) {
            system.out.println(u);
        }
    }
   
    public map getusermap() {
        map users = new hashmap();
        user user = new user();
        user.setid(new date().getseconds());
        user.setname("jack#");
        user.setaddress("china");
        user.setemail("jack@hoo.com");
        users.put("a", user);
       
        user = new user();
        user.setid(new date().getseconds());
        user.setname("tom");
        user.setaddress("china");
        user.setemail("tom@hoo.com");
        users.put("b", user);
        return users;
    }
   
    public void setusers(list users) {
        for (user u : users) {
            system.out.println(u);
        }
    }
}

  3、编写wsdd文本发布当前webservice,wsdd文件代码如下:

代码
apache.org/axis/wsdd/"
    xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
   
       
       
       
       
       
   

和上面的wsdd文件不同的是,这里多了beanmapping的配置。qname是xml中规范限定名称,由命名空间url、本地名称、前缀组成,本地名称是必需的且qname是不可变的。后面的mynsd(namespace)是必需的,是通过前面的qname指定的,mynsd后面的urn:user就和程序中的qname对应的第一个参数,第二个参数对应配置文件中的qname的mynsd冒号后面的值。languagespecifictype是javabean的类路径。

 

4、发布webservice,还是允许命令行:

java -djava.ext.dirs=lib org.apache.axis.client.adminclient -lhttp://localhost:8080/axiswebservice/services/adminservice deploycomplex.wsdd

发布后,在浏览器中请求:

http://localhost:8080/axiswebservice/servlet/axisservlet

就可以看到发布的webservice和暴露的方法了。

 

5、客户端代码的编写,这次客户端和以前有些不一样。因为这里设置了参数和返回值都是复杂类型,而不是简单的类型了。代码如下:

代码 package com.hoo.client;

import java.rmi.remoteexception;
import java.util.date;
import java.util.list;
import java.util.map;
import javax.xml.namespace.qname;
import javax.xml.rpc.parametermode;
import javax.xml.rpc.serviceexception;
import org.apache.axis.client.call;
import org.apache.axis.client.service;
import org.apache.axis.encoding.xmltype;
import org.apache.axis.encoding.ser.beandeserializerfactory;
import org.apache.axis.encoding.ser.beanserializerfactory;

import com.hoo.entity.user;

/**
 * function:axis webservice传递复杂对象,客户端
 * @author hoojo
 * @createdate dec 16, 2010 10:32:57 pm
 * @file userserviceclient.java
 * @package com.hoo.client
 * @project axiswebservice
 * @blog http://blog.111cn.net/ibm_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
@suppresswarnings("unchecked")
public class userserviceclient {
   
    private static final string url = "http://localhost:8080/axiswebservice/services/manageruser";
    private static service service = new service();
   
    public static user getuser(string name) throws serviceexception, remoteexception {
        call call = (call) service.createcall();
        call.settargetendpointaddress(url);
        qname qn = new qname("urn:user", "user");
        //call.registertypemapping(user.class, qn, new beanserializerfactory(user.class, qn), new beandeserializerfactory(user.class, qn));
        call.registertypemapping(user.class, qn, beanserializerfactory.class, beandeserializerfactory.class);
        call.setoperationname("getuserbyname");
        /*
         * 这里客户端和服务器端共用一个user,在实际开发中
         * 客户端和服务器端在不同的机器上,所以user对象可能不一样
         * 需要我们根据webservice的wsdl分析对象的属性
         */
        call.addparameter("name", xmltype.xsd_string, parametermode.in);
        call.setreturnclass(user.class);
        user user = (user) call.invoke(new object[] { "jackson" });
        return user;
    }
   
    public static void setuser(user user) throws serviceexception, remoteexception {
        call call = (call) service.createcall();
        call.settargetendpointaddress(url);
        //这里的qname的ns和wsdd文件中的对应
        qname qn = new qname("urn:user", "user");
        //这里是将对象序列化和反序列化的配置
        call.registertypemapping(user.class, qn, new beanserializerfactory(user.class, qn), new beandeserializerfactory(user.class, qn));
        call.setoperationname("setuser");
        //设置参数类型
        call.addparameter("user", qn, parametermode.in);
        call.invoke(new object[] { user });
    }
   
    public static list getusers(int i) throws serviceexception, remoteexception {
        call call = (call) service.createcall();
        call.settargetendpointaddress(url);
        //这里的qname的ns和wsdd文件中的对应
        qname qn = new qname("urn:user", "user");
        //这里是将对象序列化和反序列化的配置
        call.registertypemapping(user.class, qn, new beanserializerfactory(user.class, qn), new beandeserializerfactory(user.class, qn));
        call.setoperationname("getusers");
        call.addparameter("i", xmltype.xsd_int, parametermode.in);
        call.setreturnclass(list.class);
        list users = (list) call.invoke(new object[] { i });
        return users;
    }
   
    public static void setusers(list users) throws serviceexception, remoteexception {
        call call = (call) service.createcall();
        call.settargetendpointaddress(url);
        //这里的qname的ns和wsdd文件中的对应
        qname qn = new qname("urn:user", "user");
        //这里是将对象序列化和反序列化的配置
        call.registertypemapping(user.class, qn, new beanserializerfactory(user.class, qn), new beandeserializerfactory(user.class, qn));
        call.setoperationname("setusers");
        call.addparameter("users", xmltype.xsd_anytype, parametermode.in);
        call.invoke(new object[] { users });
    }
   
    public static void setusermap(map maps) throws serviceexception, remoteexception {
        call call = (call) service.createcall();
        call.settargetendpointaddress(url);
        //这里的qname的ns和wsdd文件中的对应
        qname qn = new qname("urn:user", "user");
        //这里是将对象序列化和反序列化的配置
        call.registertypemapping(user.class, qn, new beanserializerfactory(user.class, qn), new beandeserializerfactory(user.class, qn));
        call.setoperationname("setusermap");
        call.addparameter("maps", xmltype.xsd_anytype, parametermode.in);
        call.invoke(new object[] { maps });
    }
   
    public static map getusermap() throws remoteexception, serviceexception {
        call call = (call) service.createcall();
        call.settargetendpointaddress(url);
        //这里的qname的ns和wsdd文件中的对应
        qname qn = new qname("urn:user", "user");
        //这里是将对象序列化和反序列化的配置
        call.registertypemapping(user.class, qn, new beanserializerfactory(user.class, qn), new beandeserializerfactory(user.class, qn));
        call.setoperationname("getusermap");
        //call.addparameter("null", xmltype.xsd_anytype, parametermode.in);
        call.setreturnclass(map.class);
        map maps = (map) call.invoke(new object[]{});
        return maps;
    }
   
    public static user[] getuserarray(int i) throws serviceexception, remoteexception {
        call call = (call) service.createcall();
        call.settargetendpointaddress(url);
        //这里的qname的ns和wsdd文件中的对应
        qname qn = new qname("urn:user", "user");
        //这里是将对象序列化和反序列化的配置
        call.registertypemapping(user.class, qn, new beanserializerfactory(user.class, qn), new beandeserializerfactory(user.class, qn));
        call.setoperationname("getuserarray");
        call.addparameter("i", xmltype.xsd_int, parametermode.in);
        call.setreturnclass(user[].class);
        user[] users = (user[]) call.invoke(new object[] { i });
        return users;
    }
   
    public static void setuserarray(user[] users) throws remoteexception, serviceexception {
        call call = (call) service.createcall();
        call.settargetendpointaddress(url);
        //这里的qname的ns和wsdd文件中的对应
        qname qn = new qname("urn:user", "user");
        //这里是将对象序列化和反序列化的配置
        call.registertypemapping(user.class, qn, new beanserializerfactory(user.class, qn), new beandeserializerfactory(user.class, qn));
        call.setoperationname("setuserarray");
        call.addparameter("users", xmltype.xsd_anytype, parametermode.in);
        call.invoke(new object[] { users });
    }
   
    @suppresswarnings("deprecation")
    public static void main(string[] args) throws remoteexception, serviceexception {
        user user = new user();
        user.setid(new date().getseconds());
        user.setname("tom");
        user.setaddress("china");
        user.setemail("tom@hoo.com");
        system.out.println("============getuser=============");
        system.out.println(getuser("jack"));
        system.out.println("============setuser=============");
        setuser(user);//看服务器端控制台
        system.out.println("============getusers list=============");
        list users = getusers(3);
        for (user u : users) {
            system.out.println(u);
        }
        system.out.println("============setusers list=============");
        setusers(users);
        system.out.println("============getusermap=============");
        map map = getusermap();
        system.out.println(map);
        system.out.println("============setusermap=============");
        setusermap(map);
        system.out.println("============getuserarray=============");
        user[] arr = getuserarray(3);
        system.out.println("============setuserarray=============");
        setuserarray(arr);
    }
}

   

需要说明的是,这里传递的user和服务器端的user是同一个对象,在实际开发中应该不是同一个对象的。如java调用.net的webservice,传递的对象应该不是同一个。需要我们自己根据wsdl文件中的描述创建javabean。注意的是对象一个要序列化。

new qname("urn:user", "user")这里的qname的urn:user和wsdd文件中的对应,参数user也是和wsdd文件中的qname="mynsd:user"对应的

这里是将对象序列化和反序列化的配置

call.registertypemapping(user.class, qn, new beanserializerfactory(user.class, qn), new beandeserializerfactory(user.class, qn));

user是mapping的对象,也就是更加wsdl中参数描述创建的java对象

call.addparameter("i", xmltype.xsd_int, parametermode.in);设置参数信息,parametermode.in代表传递的参数,xmltype.xsd_int,代表参数的类型,前面的i是参数名称

call.setreturnclass(user[].class);设置返回值的类型

特别说明:

a、 如果你调用的方法有返回值,一定要设置返回值的类型。call.setreturnclass

b、 如果你调用的方法有参数,一定要设置参数的类型call.addparameter

c、 记得添加wsdl4j.jar,序列化转换的时候需要用到,否则会出现找不到类型异常

 

运行后,效果如下:

客户端:

============getuser=============

41#jackson#jackson@hoo.com#china

============setuser=============

- no returntype was specified to the call object! you must call setreturntype() if you have called addparameter().

============getusers list=============

41#jack#0#jack0@hoo.com#china

41#jack#1#jack1@hoo.com#china

41#jack#2#jack2@hoo.com#china

41#jack#3#jack3@hoo.com#china

============setusers list=============

- no returntype was specified to the call object! you must call setreturntype() if you have called addparameter().

============getusermap=============

{a=41#jack##jack@hoo.com#china, b=41#tom#tom@hoo.com#china}

============setusermap=============

- no returntype was specified to the call object! you must call setreturntype() if you have called addparameter().

============getuserarray=============

============setuserarray=============

- no returntype was specified to the call object! you must call setreturntype() if you have called addparameter().

服务器端:

37#tom#tom@hoo.com#china

37#jack#0#jack0@hoo.com#china

37#jack#1#jack1@hoo.com#china

37#jack#2#jack2@hoo.com#china

37#jack#3#jack3@hoo.com#china

{a=37#jack##jack@hoo.com#china, b=37#tom#tom@hoo.com#china}

37#jack#0#jack0@hoo.com#china

37#jack#1#jack1@hoo.com#china

37#jack#2#jack2@hoo.com#china

 

map、array、list、javabean都可以顺利转换,不管是参数还是返回值。怎么样,很简单吧!

传递内部类 

如果你传递的javabean带有内部类,那么你的内部类需要是静态化的,且一样要序列化。为account对象添加一个属性birthday,birthday是一个内部类,

代码 package com.hoo.entity;

import java.io.serializable;

/**
 * function:account entity
 * @author hoojo
 * @createdate dec 16, 2010 10:18:20 pm
 * @file account.java
 * @package com.hoo.entity
 * @project axiswebservice
 * @blog http://blog.111cn.net/ibm_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
public class account {
    private int id;
    private string name;
    private string email;
    private string address;
    private birthday birthday;
   
    public birthday getbrithday() {
        return birthday;
    }
    public void setbrithday(birthday birthday) {
        this.birthday = birthday;
    }
   
    //getter、setter
   
    @override
    public string tostring() {
        return this.id + "#" + this.name + "#" + this.email + "#" + this.address + "#" + this.birthday.getbirthday();
    }
   
    /**
     * axis中传的的内部类一定要是静态的,且要序列化
     */
    public static class birthday implements serializable {
        private static final long serialversionuid = 1l;
        private string bitthday;

//        getter、setter
    }
}


  同样我们需要在客户端调用的时候,注册类型序列化和反序列化。

qname qn = new qname("urn:account", "entity.account");

call.registertypemapping(account.class, qn, new beanserializerfactory(account.class, qn), new beandeserializerfactory(account.class, qn));

qname qn2 = new qname("urn:birthday", "account.birthday");

call.registertypemapping(birthday.class, qn2, new beanserializerfactory(birthday.class, qn2), new beandeserializerfactory(birthday.class, qn2));

而在wsdd文件中和刚才几乎一样

com.hoo. com.hoo.entity.account$birthday

是内部类的表示方式

 

本文来源:http://www.gdgbn.com/asp/28582/