zoukankan      html  css  js  c++  java
  • Ice中间件学习 02 【简单实现HelloWorld】

    注:该部分内容部分来自网络。如有侵权请联系

    一、简述

    创建一个非常easy的客户-serverIce应用,这个应用提供远程地打印功能:client发送要打印的文本给server。再由server把文本发给打印机,打印程序仅仅是把文本打印到终端。而不是真正的打印机,目的是说明客户如何与server通信。

    二、安装Ice

    Ice官方下载:http://www.zeroc.com/download.html

    2.1、安装Ice(过程略)

    2.2、配置路径

    配置环境变量:将Ice的安装路径下的bin文件夹配置到系统的path环境变量中。例如以下图:

    -1

    測试安装是否成功。仅仅须要在安装的机器上打开cmd输入slice2java命令就可以(该系列全部文章针对Java语言实现),例如以下图所看到的:

    图-2

    说明Ice配置完毕!

    三、HelloWorld实现

    3.1、使用MyEclipse开发,创建一个项目为iceTest的Javaproject,在src

    3.2、编写Slice定义

    编写不论什么Ice应用的第一个步骤就是要编写一个Slice定义,当中包括应用所用的各个接口。我们为打印应用编写了例如以下这种Slice定义:

    module demo{
    	interface Printer{
    		void printString(string s);
    	};
    };

    我们把这段代码片段保存在叫做printer.ice的文件里,存放在src文件夹下,例如以下图所看到的


    -3

    Slice定义含有一个接口。叫做Printer,该接口非常easy,仅仅提供了一个操作叫做printString,printString操作接收一个串作为它唯一的输入參数;这个串的文本将会出如今打印机上。

    3.3、编写使用Java的Ice应用

    3.3.1、编译printer.ice

    在cmd命令中进入iceTestproject中printer.ice文件所在的文件夹下,例如以下图所看到的:

    -4

    cmd中输入命令:slice2java printer.ice

    -5

    说明:slice2java编译器依据这个printer.ice文件定义生成一些Java源文件,我们眼下无需关注这些文件的确切内容,它们所包括的是编译器生成的代码,与我们在printer.ice中定义的Printer接口相相应。

    此时刷新iceTestproject,能够看到多出了非常多的文件,之所以编译以后生成的Java文件存放在demo下,是由于我们的Printer.ice文件里使用module demo定义了包路径。

    -6

    说明:demo包下的全部Java文件都报错,这是由于没有导入Ice执行所须要的jar包,我们在Ice的安装文件夹下的lib包找到ice.jar,将该jar包导入到iceTestproject下就可以。


    图-7

    3.3.2、编写和编译server

    要实现Printer接口。必须创建一个servant类,依照惯例。servant类的名字是接口的名字加上一个I后缀,所以servant类叫做PrintI,并放在PrinterI.java源文件里,存放在com.xuz.servant包中。

    package com.xuz.servant;
    import Ice.Current;
    import demo._PrinterDisp;
    public class PrintI extends _PrinterDisp {
    	@Override
    	public void printString(String s, Current current) {
    		System.out.println(s);
    	}
    }

    说明:PrintI类继承自叫做_PrinterDisp的基类,该类由slice2java编译器生成,是一个抽象类,当中含有一个printString方法。其參数时打印机要打印的串,以及类型为Ice.Current的对象,我们的printString方法的实现会简单地把它的參数写到终端,server代码其余部分在一个叫做Server.java的文件里,存在com.xuz.server包中,以下给出了其完整的代码:

    package com.xuz.server;
    import com.xuz.servant.PrintI;
    public class Server {
    	public static void main(String[] args) {
    		int status = 0;
    		Ice.Communicator ic = null;
    		try {
    			//初始化连接,args能够传一些初始化參数,如连接超时,初始化client连接池的数量等
    			ic = Ice.Util.initialize(args);
    			//创建名为SimplePrinterAdapter的适配器。并要求适配器使用缺省的协议(TCP/IP 端口为10000的请求)
    			Ice.ObjectAdapter adapter = ic.createObjectAdapterWithEndpoints("SimplePrinterAdapter", "default -p 10000");
    			//实例化一个Printer对象,为Printer接口创建一个服务对象
    			Ice.Object object = new PrintI();
    			//将服务单元添加到适配器中,并给服务对象指定名称为SimplePrinter,该名称用于唯一确定一个服务单元
    			adapter.add(object, Ice.Util.stringToIdentity("SimplePrinter"));
    			//激活适配器
    			adapter.activate();
    			//让服务在退出之前。一直持续对请求的监听
    			ic.waitForShutdown();
    		} catch (Exception e) {
    			e.printStackTrace();
    			status = 1;
    		}finally{
    			if(ic!=null){
    				ic.destroy();
    			}
    		}
    		System.exit(status);
    	}
    }
    

    说明:main的主题含有一个try块,把全部的server代码都放在当中。这段代码会在退出之前销毁通信器(假设曾今成功创建过)。要是Ice run time正常结束,这样做是必须的:程序必须调用它所创建的不论什么通信器的destroy;否则就会产生不确定的行为。

    我们把对destory的调用放进finally块,这样无论前面的try块中发生什么异常,通信器都保证会正确销毁。

    try块中主体含有实际的server代码:

    //初始化连接,args能够传一些初始化參数。如连接超时,初始化client连接池的数量等
    			ic = Ice.Util.initialize(args);
    			//创建名为SimplePrinterAdapter的适配器。并要求适配器使用缺省的协议(TCP/IP 端口为10000的请求)
    			Ice.ObjectAdapter adapter = ic.createObjectAdapterWithEndpoints("SimplePrinterAdapter", "default -p 10000");
    			//实例化一个Printer对象。为Printer接口创建一个服务对象
    			Ice.Object object = new PrintI();
    			//将服务单元添加到适配器中。并给服务对象指定名称为SimplePrinter,该名称用于唯一确定一个服务单元
    			adapter.add(object, Ice.Util.stringToIdentity("SimplePrinter"));
    			//激活适配器
    			adapter.activate();
    			//让服务在退出之前,一直持续对请求的监听
    			ic.waitForShutdown();

    这段代码包括了一下步骤:
    1)、我们调用Ice.Util.initialize初始化Ice run time(之所以把args传给这个调用。是由于server可能有run time 感兴趣的命令行參数。就这个样例而言,server不须要不论什么命令參数)。对initialize的调用返回的是一个通信器Ice.Communicator引用,这个引用是Ice run time的主句柄。
    2)、调用通信Communicator实例上的createObjectAdapterWithEndpoints,创建一个对象适配器,传入的參数是:SimplePrinterAdapter(适配器的名字)。


    3)、这时serverrun time已经初始化,实例化一个PrintI对象。为我们的Printer接口创建一个servant。
    4)、调用适配器add,告诉它有了一个新的servant。传给add的參数时我们刚才实例化的servant,再加上一个标示符,在这里"SimplePrinter"串是servant的名字(假设有多个打印机。每一个打印机都有不同的名字,更正确的说法是,都会有不同的标示符)。
    5)、接下来,调用适配器的activate方法激活适配器(适配器一開始是在holding状态创建。假设适配器处于holding状态。server端run time就会停止从相应的传输端点读取数据,不接受client发送的连接请求,这种做法在以下这种情况下非常实用:假设有非常多歌servant。它们共享同一个适配器。而在全部servant实例化之前我们不想处理请求)。一旦适配器被激活。server就会開始处理来自client的请求。
    6)、最后调用waitForShutdown。

    这种方法挂起发出调用的线程,直到server实现终止为止-或者是通过发出的一个调用关闭run time,或者是对某个信号做出相应(眼下,当我们不再须要server时,会简单地在命令行上终端它)。
    注意:虽然这里的代码不算少,但它们对全部的server都是一样的。你能够把这些代码放在一个辅助类里,然后就无需再为它费心了(Ice提供了一个辅助类:Ice.Application)。就实际的应用代码而言。server仅仅有几行代码:六行代码定义PrintI类,再加上三、四行代码实例化一个PrintI对象。并向对象适配器注冊它。

    3.3.3、编写和编译client
    client代码在Client.java中,看起来与server非常相似,存放在com.xuz.client包中,代码例如以下:

    package com.xuz.client;
    import demo.PrinterPrx;
    import demo.PrinterPrxHelper;
    public class Client {
    	public static void main(String[] args) {
    		int status = 0;
    		Ice.Communicator ic = null;
    		try {
    			//初始化通信器
    			ic = Ice.Util.initialize(args);
    			//传入远程服务单元的名称、网络协议、IP以及端口,获取Printer的远程代理,这里使用stringToProxy方式
    			Ice.ObjectPrx base = ic.stringToProxy("SimplePrinter:default -p 10000");
    			//通过checkedCast向下转型。获取Printer接口的远程。并同一时候检測依据传入的名称获取服务单元是否Printer的代理接口。假设不是则返回null对象
    			PrinterPrx printer = PrinterPrxHelper.checkedCast(base);
    			if(printer == null){
    				throw new Error("Invalid proxy");
    			}
    			//把Hello world传给服务端。让服务端打印出来,由于这种方法终于会在服务端上执行
    			printer.printString("Hello World!");
    		} catch (Exception e) {
    			e.printStackTrace();
    			status = 1;
    		}finally{
    			if(ic != null){
    				ic.destroy();
    			}
    		}
    		System.exit(status);
    	}
    }

    说明:和server一样
    1)、调用Ice.initialize初始化Ice run time.
    2)、获取远地打印机的代理,调用通信器的stringToProxy创建一个代理,所用參数是:"SimplePrinter:default -p 10000",注意。这个串包括了对象标示符和server所用的端口号一致
    3)、stringToProxy返回的代理类型是Ice.ObjectPrx,这种类型位于接口和类的继承树的根部。可是实际与我们的打印机交谈。我们须要的嘶吼Printer接口、而不是Object接口的代理,为此,须要调用PrinterPrxHelper.checkCast进行向下转型。这种方法会发送一条消息给server,实际询问"这是Printer接口的代理吗?",假设是,这个调用就会返回Printer的一个代理,假设代理代表的是其它类型的接口。这个调用就会返回一个空代理。
    4)、測试向下转型是否成功。假设不成功,抛出错误消息,终止客户。
    5)、如今。在地址空间里面有了一个活的代理,能够调用printerString方法,把hello world串传给它,server会在它的终端上打印出这个串。
    3.3.4、执行服务和client
    在MyEclipse中,首先执行Server,启动server。再执行Client。在server的Console中我 们会看到打印出了"Hello World!".

    四、总结
    在本节主要介绍了一个简单的入门级(完整)的client和server的实例。从上可知,编写Ice应用涉及一下几个步骤:
    1、编写Slice定义并编译它。
    2、编写server并编译它。
    3、编写client并编译它。


    五、源代码下载:
    Ice简单应用源代码下载

    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
              
  • 相关阅读:
    什么是兼容性测试?请举例说明如何利用兼容性测试列表进行测试。
    如何定位测试用例的作用?
    为什么要在一个团队中开展软件测试工作?
    安装git和小乌龟
    idea配置tomcat
    Maven下载及配置
    JDK(1.6,1.7,1.8,10,11)64位解压版配置使用
    SQL中Case When的用法
    mybatis批量新增和修改删除
    org.apache.ibatis.binding.BindingException表示mapper.xml没找到
  • 原文地址:https://www.cnblogs.com/mqxnongmin/p/10959600.html
Copyright © 2011-2022 走看看