`
zhaoningbo
  • 浏览: 624073 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Zeroc Ice 返回"值类型对象"的实现

阅读更多
引言:

    最近比较搓,忙得没空写写博客,回想一下又好像没忙什么事。得反省一下了,当然此是后话。

    本文就Zeroc Ice方法返回复杂类的对象(return by-value, not by-reff),做以简单说明。之所以有这篇文章,只因笔者发现网上流传的中文文章中有这么个空白,英文的也没个直接的说明。

    此文用BBCode编写。

内容:

    一、ICE方法返回对象的实现
    二、机制的简要说明
    三、一个Exception的解决
    四、资源信息

正文:

一、ICE方法返回对象的实现。

    1,模型设计。



    如上图“class_diagram.JPG”所示,Bond(债券)为JavaBean,MainOperator(主操作者)有一个方法“Bond getBean(String beanUID)”返回一个JavaBean。

    2,具体实现。(各代码所在文件名,请参看首注释中的“file”注释)

    A)slice定义

/*
 * file:    BondDef.ice
 * by:      zhaoningbo
 * date:    2011-07-25 15:51
 */
#ifndef BEAN_BOND_DEF
#define BEAN_BOND_DEF
module com{
    module number{
        module bean{
            
            // 债券Bean
            class Bond{
            
                // Files
                string bName;
                string bCode;
                
                // Methods
                string getbName();
                void setbName(string bName);
                
                string getbCode();
                void setbCode(string bCode);
                
            };
        
        };
    };
};
#endif


/*
 * file:    MainOperatorDef.ice
 * by:      zhaoningbo
 * date:    2011-07-25 16:02
 */
#ifndef OPERATOR_MAINOPERATOR_DEF
#define OPERATOR_MAINOPERATOR_DEF
module com{
    module number{
    
        // 预定义
        module bean{
            class Bond;
        };
    
        module operator{
        
            // 总执行者
            interface MainOperator{
                // 获取Bond对象
                idempotent com::number::bean::Bond getBean(string beanUID);
            };
        };
    };
};
#endif


    B)slice2java生成ice的java接口类集

    C)编写服务方

    (i)实现Bond。因为Bond是个抽象类,需要给定一个实现BondI。

/*
 * file:    BondI.java
 */
package com.number.bond;

import java.io.Serializable;
import Ice.Current;
import com.number.bean.Bond;

/**
 * 自定义债券Bean
 * 注:实现Bond时,直接实现Override即可,无需添加其他的类元素。
 * @author zhnb
 *
 */
public class BondI extends Bond implements Serializable {
    
    private static final long serialVersionUID = 8758902536680272427L;
    
    @Override
    public String getbCode(Current current) {
        return this.bCode;
    }

    @Override
    public String getbName(Current current) {
        return this.bName;
    }

    @Override
    public void setbCode(String bCode, Current current) {
        this.bCode = bCode;
    }

    @Override
    public void setbName(String bName, Current current) {
        this.bName = bName;
    }

}


    (ii)加个dao层数据提供者(仅图好看)

/*
 * file:    BondLCData.java
 */
package com.number.dao;

import java.io.Serializable;
import com.number.bond.BondI;

/**
 * 数据提供类
 * @author zhnb
 *
 */
public class BondLCData implements Serializable {

    private static final long serialVersionUID = -5413237344986060553L;

    // 单值
    public static BondI BONDLC_DATA_SINGLE = null;
    static{
        BondI bondI= new BondI();
        bondI.setbCode("600006");
        bondI.setbName("青岛啤酒");
        
        BONDLC_DATA_SINGLE = bondI;
    }
    
}


    (iii)实现操作者业务类

/*
 * file:    MainOperatorI.java
 */
package com.number.operator;

import java.io.Serializable;
import Ice.Current;
import com.number.bean.Bond;
import com.number.dao.BondLCData;

/**
 * 主操作业务类
 * @author zhnb
 *
 */
public class MainOperatorI extends _MainOperatorDisp implements Serializable {

    private static final long serialVersionUID = 1017768576442347413L;

    @Override
    public Bond getBean(String beanUID, Current current) {
        
        // 获取一个BondLC对象
        Bond bond = BondLCData.BONDLC_DATA_SINGLE;
        
        return bond;
    }

}


    (ix)发布业务类,注册到服务

/*
 * file:    MainOperatorServer.java
 */
package com.number.operator;

import java.io.Serializable;
import Ice.ObjectAdapter;

/**
 * 主操作服务发布者
 * @author zhnb
 *
 */
public class MainOperatorServer implements Serializable {

    private static final long serialVersionUID = -691557224337330222L;

    public static void main(String[] args) {

        // 0, 声明执行状态
        int status = 0;
        Ice.Communicator ic = null;

        try {

            // 1, 初始化环境
            // 加载属性文件
            ic = Ice.Util.initialize();

            // 2, 初始化Adapter

            String name = "MainOperatorServer";
            String endpoints = "default -h 127.0.0.1 -p 9999";
            ObjectAdapter objAdapter = ic.createObjectAdapterWithEndpoints(
                    name, endpoints);

            // 3, 创建伺服者
            Ice.Object servant = new MainOperatorI();

            // 4, 添加伺服者至适配器
            objAdapter.add(servant, Ice.Util.stringToIdentity("MainOperatorUID"));

            // 5, 激活
            objAdapter.activate();

System.out.println("<<MainOperatorUID started>>");
            // 6, 等待关闭
            ic.waitForShutdown();

        } catch (Exception e) {
            e.printStackTrace();
            status = 1;
        } finally {
            if (ic != null) {
                ic.destroy();
            }
            System.exit(status);
        }

    }


    以上类中MainOperatorI主是个普通接口的实现方式,很简单。BondI是个类的实现方式,需要留意。

    D)编写客户方

    (i)编写请求者

/*
 * file:    MainOperatorClient.java
 */
package com.number.operator;

import java.io.Serializable;
import Ice.ObjectPrx;
import com.number.bean.Bond;
import com.number.bond.ObjectFactory4Bond;
import com.number.except.UGenericException;

/**
 * 请求数据者(通用接口方式)
 * @author zhnb
 *
 */
public class MainOperatorClient implements Serializable {

    private static final long serialVersionUID = -3207025201067021445L;

    /**
     * 获取债券对象
     * @param bondUID   债券标志
     * @return
     */
    public Bond getBean(String bondUID){
        
        Bond bond = null;
        
        try {
            // 获取代理
            MainOperatorPrx mainOperatorPrx = this.getOwnPrx();

/*
            // 添加自定义类
            Ice.ObjectFactory factory = new ObjectFactory4Bond();
            this.ic.addObjectFactory(factory, com.number.bond.BondI.ice_staticId());
 */            
            bond = mainOperatorPrx.getBean("anyThingAsArg");
            
        } catch (UGenericException e) {
            e.printStackTrace();
        }
        
        return bond;
    }
    
    // =========以<下>为私有方法,提供ICE支撑。=========
    // 获取服务端提供的代理
    private MainOperatorPrx mainOperatorPrx = null;

    // Ice通讯员(为回收资源时,方便自动回收)
    private Ice.Communicator ic = null;

    // GC回收时,自动销毁Ice.Communicator。
    @Override
    protected void finalize() throws Throwable {
        if (this.ic != null) {
            ic.destroy();
        }
        super.finalize();
    }

    /**
     * 获取代理
     * 
     * @return 本类的代理
     */
    private MainOperatorPrx getOwnPrx() throws UGenericException {

        // 代理为空时,自动获取代理。
        if (this.mainOperatorPrx == null) {
            // 环境为空时,初始化环境
            if (this.ic == null) {
                // 1, 初始化环境
                ic = Ice.Util.initialize();
            }
            // 2, 创建代理基类对象
            String str = "MainOperatorUID:default -h 127.0.0.1 -p 9999";
            
            ObjectPrx objPrx = this.ic.stringToProxy(str);
            // 3, 获取代理
            this.mainOperatorPrx = MainOperatorPrxHelper.checkedCast(objPrx);

            // 4, 测试是否可用,不可用时抛出异常。
            if (this.mainOperatorPrx == null) {
                throw new UGenericException(str + ", request proxy faild.");
            }
        }
        return this.mainOperatorPrx;
    }
    // =========以<上>为私有方法,提供ICE支撑。=========
}


    (ii)为客户端写个手工测试类

/*
 * file:    StartAllClient.java
 */
package com.number.start;

import java.io.Serializable;
import com.number.bean.Bond;
import com.number.operator.MainOperatorClient;

/**
 * 启动使用者
 * @author zhnb
 *
 */
public class StartAllClient implements Serializable {

    private static final long serialVersionUID = -6282697303788648813L;

    public static void main(String[] args) {

        MainOperatorClient moc = new MainOperatorClient();
        Bond bond = moc.getBean("something");
        
        StringBuffer info = new StringBuffer();
        if (bond == null) {
            info.append("null");
        } else {
            info.append("Bond@" + bond.hashCode() + ":");
            
            info.append("bName=" + bond.bName);
            info.append(",bCode=" + bond.bCode);
            
            info.append(":");
            info.append("bName=" + bond.getbName());
            info.append(",bCode=" + bond.getbCode());
        }
        
        System.out.println(info.toString());
        System.exit(0);
    }

}


    OK,看样子写完了,可以跑了吧。试个……(提交一下,我去瞅个行号~。=)

念叨着,“先启服务run 'MainOperatorServer'……再启客户run 'StartAllClient'”……

    哦~&*……*出错了!

Exception in thread "main" Ice.NoObjectFactoryException
    reason = ""
    type = "::com::number::bean::Bond"
	at IceInternal.BasicStream.readObject(BasicStream.java:1444)


    Why? ?? !? 不是一直这么个写法嘛?!

    ——如果是这么个写法,我也就不花功夫写这篇文章了。

二、机制的简要说明

   返回值有两种方式,一种是Ice最喜欢的(也是最推荐的)“引用”方式,另一种是“传值”方式。在ICE中的含意如下:

   “引用”,即客户端不会拿到类型实体的副本,只拿到一个代理,可以抽象成一个远程指针(C系)或者一个对象引用(J系)。
   “传值”,跟“引用”相对,即拿到类型实体的副本。
   (此处略去二者特点,即使用范围,约一千字。)

    因此引用的时候,就类似于“远程过程调用”的感觉,属于“行为”性。可抽象成一系列的接口,实现C-S间的规范协议。而传值时,有“序列反序列”的味道,属于“实体”性。需要传方有个打包成序列的模板,收方有个解包成对象的模板。回观上文报错,释然了。

三、一个Exception的解决

    一个Exception指的是“NoObjectFactoryException”,无对象工厂异常。当客户方拿到一箱Bond的零件后,他找不到工厂给的对象装配图。傻眼了的意思。

   人工建图。没有拿到模型,但是知道有个“Bond.java”抽象的不能使,那就直接实现一个最基础的吧。造个BondI当临时模板使着吧,先!

/*
 * file:    BondI.java
 */
package com.number.bond;

import java.io.Serializable;
import Ice.Current;
import com.number.bean.Bond;

/**
 * 自定义债券Bean(LC, 本地类)
 * @author zhnb
 *
 */
public class BondI extends Bond implements Serializable {
    
    private static final long serialVersionUID = 8758902536680272427L;
    
    // Methods
    @Override
    public String getbCode(Current current) {
        return this.bCode;
    }

    @Override
    public String getbName(Current current) {
        return this.bName;
    }

    @Override
    public void setbCode(String bCode, Current current) {
        this.bCode = bCode;
    }

    @Override
    public void setbName(String bName, Current current) {
        this.bName = bName;
    }

}


    建好了,怎么告诉装配工呢。ICE的装配工,会看已有的图纸,也会手机上网去ObjectFactory试着查还没装到自己包里的图纸。那我们就把装配图传到ObjectFactory上去吧!

    (i)创建一个ObjectFactory规范下的装配图

/*
 * file:    ObjectFactory4Bond.java
 */
package com.number.bond;

import Ice.Object;
import Ice.ObjectFactory;

/**
 * 传值方式,必须实现一个自定义类工厂。
 * @author zhnb
 *
 */
public class ObjectFactory4Bond implements ObjectFactory {

    @Override
    public Object create(String type) {
        System.out.println("!!>type=" + type);
        if (type.equals(com.number.bond.BondI.ice_staticId())) {
            return new BondI();
        }
        return null;
    }

    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }

}


    (ii)拿到这箱Bond前,把装配图传到ObjectFactory上去。

    定位: 正文 | 一、ICE方法返回对象的实现 | 2,具体实现。| D)编写客户方
    找到:“MainOperatorClient.java”第34~38行,把注释部分放出来。

    注释掉的这两行代码,将装配图“BondI”放到ObjectFactory上去。以备装配工查看。

    (iii)再次运行,通过。显示如下

!!>type=::com::number::bean::Bond
Bond@12830537:bName=青岛啤酒,bCode=600006:bName=青岛啤酒,bCode=600006


四、资源信息

    你可以在code google上下载到此demo的源代码,只需热身一下你的SVN。

svn checkout http://number-icedemo-base.googlecode.com/svn/trunk/ number-icedemo-base-read-only


补充:

    有未说明清楚的问题,欢迎尾随追贴。~,=




  • 大小: 12.2 KB
2
3
分享到:
评论

相关推荐

    Zero Ice中文教程

    2. **接口与多态(Interfaces and Polymorphism)**: Ice支持接口定义和多态性,允许服务提供者通过实现特定接口来暴露功能,而客户端则通过接口调用服务,实现松耦合。 3. **序列化(Serialization)**: Ice有自己的...

    zero ICE快速入门java版

    zero ICE快速入门文档, ice是最优秀的rpc框架。 4、开发服务端代码如下 步骤一:编写Servant类即带有Disp的存根文件也就是说继承_HelloWorldDisp 这个类,这个类是个抽象类定义如下: public abstract class _...

    Zero ICE 3.5.1 jar

    远程调用框架 Zero ICE 3.5.1 jar

    Zero Ice 3.6源码

    在深入研究Zero Ice 3.6源码时,你可以了解上述技术的实现细节,学习如何使用这些功能来构建高效、可靠的分布式系统。通过阅读ice-master目录下的源代码,你可以探索ICE的内部工作机制,包括协议解析、网络通信、...

    基于ICE中间件实现的传文件

    在IT行业中,ICE(Internet Communications Engine)是一种流行的分布式对象中间件,由Object-oriented Software Corporation(OSCC)开发,现在属于Zope Corporation。ICE提供了一种跨语言、跨平台的通信框架,使得...

    Ice zero分布式程序设计2分

    1. **类型安全**:Ice Zero使用强类型协议,确保了跨网络的数据交换是类型安全的,避免了数据转换错误。 2. **多语言支持**:Ice Zero支持多种编程语言,如C++、Java、Python等,这使得跨语言的分布式协作变得容易...

    AlphaZero框架实现_alphazero_alphazero框架实现_

    AlphaZero框架实现是一种先进的强化学习算法,源自DeepMind在2017年提出的著名研究,它在围棋、国际象棋和日本将棋等复杂棋类游戏中取得了超越人类顶尖选手的表现。AlphaZero的核心思想是结合了蒙特卡洛树搜索(MCTS...

    zeroc ice教程 ice环境配置 Ice中文教程 C++ ICE java ICE ICE入门 ice基础教程 ice开发文档

    Zeroc ICE是一个开源的中间件平台,它支持C++、Java、Python、.NET等语言的分布式对象通信。ICE全称Internet Communications Engine,即互联网通信引擎,是一种用于开发分布式计算应用的强大工具。本文档主要围绕ICE...

    ice培训(服务、接口)ppt

    Slice是Zero Ice用于定义对象接口和类型的抽象语言,它与实现语言无关,使得客户端和服务器端可以使用不同的编程语言。Slice文件包括接口、操作、异常定义以及基本数据类型的描述。通过Slice编译器,定义会被转换为...

    ice_3.7.0_linux版

    Zero ICE,Zeroc ICE,ice,linux,2017年最新版的Zero ICE版本3.7.0,linux版本 Zero ICE,Zeroc ICE,ice,linux,2017年最新版的Zero ICE版本3.7.0,linux版本

    Ice通信框架原理与实践

    Ice,全称为“Internet Communication Engine”,是一种高性能、跨平台的分布式对象中间件,它提供了强大的接口定义语言(IDL)来定义服务接口,并能够自动在多种编程语言之间生成绑定代码。 1. **Ice通信框架基础*...

    ZeroC Ice 3.7.3 源码与中文教程.rar

    Ice 是一种面向对象的中间件平台。从根本上说,这意味着 Ice 为构建面 向对象的客户-服务器应用提供了工具、 API 和库支持。 Ice 应用适合在异 种环境中使用:客户和服务器可以用不同的编程语言编写,可以运行在不 ...

    Ice 分布式程序设计 中文PDF版_C++_Zero_

    ZERO-ICE是一个强大的、面向对象的、基于组件的中间件,它允许程序员在多种语言之间创建无缝的、高性能的网络应用程序,而无需关心底层的通信细节。本书主要涵盖了以下核心知识点: 1. **ICE简介**:ICE是一种跨...

    ICE客户端与服务端通信Demo

    平台编译环境:VS2017 ICE版本:3.7.7 ICEbuilder:5.0.9 源码中有两套程序: Server:启动服务器,等待连接 。连接后可双方通信 Client:连接服务器,与服务器通讯。 Slice: 手写几个接口即可。

    Zero ICE 中文文档

    一种支持 C++ java语言的Client /server 服务方式中文文档。。

    Ubuntu-zeroc-ice 环境安装

    5. 安装db5.3-util:Zeroc-ICE支持数据库热备份功能,db5.3-util是实现该功能的依赖工具。需要使用apt-get install命令进行安装。 6. 验证安装:安装完成后,使用icegridnode --version命令检查Zeroc-ICE的版本,以...

    Ice 3.4.1 在ARM上移植, 源代码补丁

    ICE 3.4.1 在移植到ARM Linux中时,double型的数据会有错误。见我在ZeroC发的帖子: http://www.zeroc.com/forums/bug-reports/5308-double-data-format-arm-linux-not-correct.html 在移植前,需要对源代码进行一些...

    ZeroC ICE 简单介绍及代码

    介绍ICE互联网通讯引擎是什么,以及其工作原理。附有简单的源代码,可以实现测试使用。

Global site tag (gtag.js) - Google Analytics