• 六、传递、返回复杂类型的对象


    上面的服务传递的是简单数据类型,返回的也是简单数据类型。下面我们用JavaBean 、List、Map、Array等返回值或参数完成WebService。

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

    代码
    package com.hoo.entity;

    import java.io.Serializable;

    /**
    * <b>function:</b>User Entity
    *
    @author hoojo
    * @createDate Dec 16, 2010 10:20:02 PM
    * @file User.java
    * @package com.hoo.entity
    * @project AxisWebService
    * @blog
    http://blog.csdn.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;

    /**
    * <b>function:</b>axis WebService传递复杂类型数据
    *
    @author hoojo
    * @createDate Dec 16, 2010 10:21:06 PM
    * @file ManagerUser.java
    * @package com.hoo.service
    * @project AxisWebService
    * @blog
    http://blog.csdn.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<User> getUsers(int i) {
    List
    <User> users = new ArrayList<User>();
    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<String, User> 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<String, User> getUserMap() {
    Map
    <String, User> users = new HashMap<String, User>();
    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<User> users) {
    for (User u : users) {
    System.out.println(u);
    }
    }
    }

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

    代码
    <?xml version="1.0" encoding="UTF-8"?>
    <deployment xmlns="http://xml.apache.org/axis/wsdd/"
    xmlns:java
    ="http://xml.apache.org/axis/wsdd/providers/java">
    <service name="ManagerUser" provider="java:RPC">
    <parameter name="className" value="com.hoo.service.ManagerUser" />
    <parameter name="allowedMethods" value="*" />
    <parameter name="scope" value="request" />
    <!-- 这里的urn:User和new QName("urn:User", "User")这里是对应的 -->
    <beanMapping qname="myNSD:User" xmlns:myNSD="urn:User" languageSpecificType="java:com.hoo.entity.User"/>
    </service>
    </deployment>

    和上面的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;

    /**
    * <b>function:</b>axis WebService传递复杂对象,客户端
    *
    @author hoojo
    * @createDate Dec 16, 2010 10:32:57 PM
    * @file UserServiceClient.java
    * @package com.hoo.client
    * @project AxisWebService
    * @blog
    http://blog.csdn.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<User> 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
    <User> users = (List<User>) call.invoke(new Object[] { i });
    return users;
    }

    public static void setUsers(List<User> 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<String, User> 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<String, User> 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
    <String, User> maps = (Map<String, User>) 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
    <User> users = getUsers(3);
    for (User u : users) {
    System.out.println(u);
    }
    System.out.println(
    "============setUsers List=============");
    setUsers(users);
    System.out.println(
    "============getUserMap=============");
    Map
    <String, User> 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;

    /**
    * <b>function:</b>Account Entity
    *
    @author hoojo
    * @createDate Dec 16, 2010 10:18:20 PM
    * @file Account.java
    * @package com.hoo.entity
    * @project AxisWebService
    * @blog
    http://blog.csdn.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文件中和刚才几乎一样

    <beanMapping qname="myNSD:entity.Account" xmlns:myNSD="urn:Account" languageSpecificType="java:com.hoo.entity.Account"/>

    <beanMapping qname="myNSD:Account.Birthday" xmlns:myNSD="urn:Birthday" languageSpecificType="java:com.hoo.entity.Account$Birthday"/>com.hoo. com.hoo.entity.Account$Birthday是内部类的表示方式

  • 作者:hoojo
    出处:
    blog:http://blog.csdn.net/IBM_hoojo
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权所有,转载请注明出处 本文出自:
分享道版权所有,欢迎转载,转载请注明出处,谢谢
收藏
关注
评论
  • 相关阅读:
    Sys 模块
    Select,poll,epoll复用
    Urllib模块
    多线程模块
    设计模式四:观察者,模板方法,命令,状态,职责链条,解释器,中介者,访问者,策略,备忘录,迭代器
    设计模式三:适配器,桥接,组合,装饰,外观,享元,代理
    设计模式二:建造者,原型,单例
    【Unix 网络编程】TCP状态转换图详解(转)
    Mysql系列:MySql 数据库设计与基本使用
    lombok builder源码解读
  • 原文地址:https://www.cnblogs.com/hoojo/p/1911380.html
  • Copyright © 2020-2023  润新知