本文接上篇博文《ICE通信框架》如果你还没有接触过ice请先阅读我的上篇博文 http://blog.csdn.net/liuzhoulong/archive/2011/03/04/6223450.aspx
本文将结合实际项目,做一个基于 ice的实际项目实例应用,该实例完成客户端调用服务端接口完成消息发送,计算的功能。
1,创建java项目ICEServer,导入ice.jar.
2,在项目下创建slice文件夹,编写model.ice,service.ice,service2.ice文件,其内容如下
model.ice
#ifndef _MODEL #define _MODEL module com { module alan { module generated { module model { /**定义整型数组**/ sequence<int> IntegerArray; /**自定义Map类型**/ dictionary<string, string> CustomMap; /**消息类型**/ enum MessageType {ERROR,INFO,WARNING}; /**计算操作类型**/ enum CalcType {Adds,Subtract,Multiply,Divide}; /**消息的操作类型**/ enum ActionType {Add,Remove,Stop,Start,Pause}; /** 消息结构 **/ ["java:getset"] struct Message { /**消息类型**/ MessageType type; /**消息类型**/ ActionType action; /**相关id**/ IntegerArray relatedIds; /**扩展属性**/ CustomMap extention; }; }; }; }; }; #endif
service.ice
#ifndef _GENERATED #define _GENERATED #include <model.ice> module com { module alan { module generated { interface MessageServiceIce { /** * 向ice服务发送信息 * @param message 消息内容 * @return true 成功 false 失败 */ string sendMessage(model::Message msg); }; }; }; }; #endif
service2.ice
#ifndef _GENERATED #define _GENERATED #include <model.ice> module com { module alan { module generated { interface CalcServiceIce { /** * 服务端计算方法 * @param d1 计算数1 * @param d2 计算数2 * @param type 计算方式 * @return true 成功 false 失败 */ double calc(double d1, double d2, model::CalcType cal); }; }; }; }; #endif
3.dos环境下执行
cd E:/workspace/ICEService/slice
E:/Ice-3.3.0/bin/slice2java -I. --output-dir=../src *.ice //生产代码
E:/Ice-3.3.0/bin/slice2html -I. --output-dir=doc *.ice//生产doc文档,可以忽略
将生产generated包下代码以jar包方式导出icetest.jar,并在项目中建立lib目录放入其中(把ice.jar也放入lib下,以备后用),可以删除其生产代码,以jar方式调用其代码。
4,编写发布接口实现代码和服务器端代码
CalcServiceIceImpl .java实现数学计算:
package com.alan.generated.servant; import Ice.Current; import com.alan.generated._CalcServiceIceDisp; import com.alan.generated.model.CalcType; /** * @author zcq * @version 创建时间:2015-4-23 下午06:25:17 * 实现数学计算 */ public class CalcServiceIceImpl extends _CalcServiceIceDisp{ public double calc(double num1, double num2, CalcType type, Current arg3) { double re = 0.0d; switch (type) { case Adds: re = num1 + num2; break; case Subtract: re = num1 - num2; break; case Multiply: re = num1 * num2; break; case Divide: re = num1 / num2; break; default: break; } return re; } }
MessageServiceIceImpl .java实现发送消息
package com.alan.generated.servant; import java.util.Arrays; import Ice.Current; import com.alan.generated._MessageServiceIceDisp; import com.alan.generated.model.Message; /** * @author zcq * @version 创建时间:2015-4-23 下午06:51:47 * 发送消息 */ public class MessageServiceIceImpl extends _MessageServiceIceDisp { public String sendMessage(Message msg, Current __current) { String str = msg.getType() +" "+ msg.getAction()+" " + Arrays.toString(msg.getRelatedIds()); return str; } }
IceService .java实现服务器端接口注册:
package com.alan.generated.server; import Ice.Communicator; import Ice.ObjectImpl; import com.alan.generated.servant.CalcServiceIceImpl; import com.alan.generated.servant.MessageServiceIceImpl; /** * @author zcq * @version 创建时间:2015-4-23 下午06:52:27 * 服务器端接口 */ public class IceService { public static void main(String[] args){ int status = 0; Communicator ic = null; try{ ic = Ice.Util.initialize(args); Ice.ObjectAdapter adapter = ic.createObjectAdapterWithEndpoints("testAdapter", "tcp -h *"); ObjectImpl object1 = new MessageServiceIceImpl(); ObjectImpl object2 = new CalcServiceIceImpl(); adapter.add(object1, ic.stringToIdentity("messageService")); adapter.add(object2, ic.stringToIdentity("calcService")); adapter.activate(); ic.waitForShutdown(); } catch (Ice.LocalException e) { e.printStackTrace(); status = 1; } catch (Exception e) { System.err.println(e.getMessage()); status = 1; } if (ic != null) { try { ic.destroy(); } catch (Exception e) { System.err.println(e.getMessage()); status = 1; } } System.exit(status); } }
5,发布接口
在项目下创建deploy文件夹,在其下创建config-ice.grid配置文件
IceGrid.InstanceName=IceTestServiceGrid # 1 # # The IceGrid locator proxy. # Ice.Default.Locator=IceTestServiceGrid/Locator:tcp -h 127.0.0.1 -p 9600 #2 # # IceGrid registry configuration. # IceGrid.Registry.Client.Endpoints=tcp -h 127.0.0.1 -p 9600 #3 IceGrid.Registry.Server.Endpoints=tcp #4 IceGrid.Registry.Internal.Endpoints=tcp #5 IceGrid.Registry.Data=E:\eclipse_workspace\icetest2\db\rescenter_registry #6 IceGrid.Registry.PermissionsVerifier=IceTestServiceGrid/NullPermissionsVerifier #7 IceGrid.Registry.AdminPermissionsVerifier=IceTestServiceGrid/NullPermissionsVerifier #8 IceGrid.Registry.SSLPermissionsVerifier=IceTestServiceGrid/NullSSLPermissionsVerifier #9 IceGrid.Registry.AdminSSLPermissionsVerifier=IceTestServiceGrid/NullSSLPermissionsVerifier #10 # # IceGrid SQLconfiguration if using SQL database. # #Ice.Plugin.DB=IceGridSqlDB:createSqlDB #11 #IceGrid.SQL.DatabaseType=QSQLITE #12 #IceGrid.SQL.DatabaseName=register/Registry.db #13 # # #Ice Error andStandard output Set # #Ice.StdErr=master/stderr.txt #14 #Ice.StdOut= master/stdout.txt #15 # #Trace Registryproperties # Ice.ProgramName=IceMaster #16 IceGrid.Registry.Trace.Node=3 #17 IceGrid.Registry.Trace.Replica=3 #18 # # IceGrid node configuration. # IceGrid.Node.Name=node1 #19 IceGrid.Node.Endpoints=tcp #20 IceGrid.Node.Data=E:\eclipse_workspace\icetest2\db\node1 #21 IceGrid.Node.CollocateRegistry=1 #22 #IceGrid.Node.Output=db #23 #IceGrid.Node.RedirectErrToOut=1 #24 # # Trace properties. # IceGrid.Node.Trace.Activator=1 #25 IceGrid.Node.Trace.Adapter=2 #26 IceGrid.Node.Trace.Server=3 #27 # # Dummy username and password for icegridadmin. # IceGridAdmin.Username=foo #28 IceGridAdmin.Password=bar #29 #set server active Connection Managerment #Ice.ACM.Server=60 #配置项说明: #1 为这个应用实例指定一个唯一的标识 # 2 注册服务的端点信息(主注册服务和所有的从注册服务),节点注册时要用到 # 3 客户端访问注册服务器的端点信息 # 4 服务访问注册服务器的端点信息,通常是default # 5 内部访问端点信息,通常是default,节点用这个端口和注册服务通信 # 6 注册服务的数据目录的路径 # 7 设定防火墙安全代理,从而控制客户端访问注册表时可用的权限 # 8 设定防火墙安全代理,从而控制注册表管理者可用的权限 # 9 设定SSL安全代理,从而设定客户端访问注册表时的SSL安全访问机制 # 10 设定SSL安全代理,从而设定注册表管理者的SSL安全访问机制 # 11 指定Ice对象序列化的机制,如果不设置,默认用Freeze机制 # 12 指定使用数据库的类型 #13 指定使用数据库的名称 #14 指定标准错误输出文件 #15 指定标准输出文件 #16 指定主注册服务的名称 #17 指定主注册服务跟踪节点信息的级别(0~3),默认为0 #18 指定主/从热备注册服务的跟踪级别(0~3),默认为0 # 19 定义节点的名称,必须唯一 # 20 节点被访问的端口信息,注册服务使用这个端点和节点通信,通常设为default # 21 节点的数据目录的路径 # 22 定义节点是否和注册服务并置在一起,设为1时并置,设为0时不并置 # 23 节点标准输出信息重定向蹈的目录路径,会自动生成输出文件 # 24 节点上的服务程序的标准错误重定向到标准输出 # 25 激活器跟踪级别,通常有0,1,2,3级,默认是0 # 26 对象适配器跟踪级别,通常有0,1,2,3级,默认是0 # 27 服务跟踪级别,通常有0,1,2,3级,默认是0 # 28 IceGrid管理器登录该应用的用户名 # 29 IceGrid管理器登录该应用的密码
根据需要在当前目录下创建db/node1,db/rescenter_registry文件夹
创建application.xml文件
<icegrid> <application name="icetest2"> <server-template id="icetest2-server-template"> <parameter name="index" /> <server id="rescenter_${index}" exe="C:/Program Files/Java/jdk1.7.0_15/bin/java" activation="on-demand"> <!---server -Xms128m -Xmx256m -d64 -XX:PermSize=128m--> <option>-classpath</option> <option>E:\eclipse_workspace\icetest2\src</option> <option>-Djava.ext.dirs=E:\eclipse_workspace\icetest2\lib</option> <option>-server</option> <option>com.alan.generated.server.IceService</option> <adapter name="testAdapter" endpoints="tcp" replica-group="ReplicatedTestAdapter" /> <property name="Ice.ThreadPool.Server.SizeMax" value="3000" /> </server> </server-template> <replica-group id="ReplicatedTestAdapter"> <load-balancing type="adaptive" load-sample="1" n-replicas="1" /> <object identity="messageService" type="::com::alan::generated::servant::MessageServiceIceImpl" /> <object identity="calcService" type="::com::alan::generated::servant::CalcServiceIceImpl" /> </replica-group> <node name="node1"> <server-instance template="icetest2-server-template" index="1" /> </node> </application> </icegrid>
创建start_server.bat
path=%path%;D:/Program Files/ZeroC/Ice-3.5.1/bin cd E:\eclipse_workspace\icetest2\deploy icegridnode --Ice.Config=E:\eclipse_workspace\icetest2\deploy\config-ice.grid --deploy application.xml pause
创建完成后就可以双击start_server.bat来启动服务了
icegridnode --Ice.Config=config-ice.grid
6,创建客户端调用项目ICEClient,导入ice.jar以及前面生产的icetest.jar,在项目下创建IceClient .java
package com.alan.generated.client; import java.util.HashMap; import java.util.Map; import Ice.Communicator; import Ice.InitializationData; import Ice.Util; import com.alan.generated.CalcServiceIcePrx; import com.alan.generated.CalcServiceIcePrxHelper; import com.alan.generated.MessageServiceIcePrx; import com.alan.generated.MessageServiceIcePrxHelper; import com.alan.generated.model.ActionType; import com.alan.generated.model.CalcType; import com.alan.generated.model.Message; import com.alan.generated.model.MessageType; /** * @author zcq * @version 创建时间:2015-4-23 下午07:09:44 * 客户端调用项目 */ public class IceClient { public static void main(String[] args){ int status = 0; Communicator ic = null; try{ String str = String.format("%s:%s -h %s -p %s", "IceTestServiceGrid/Locator","tcp" ,"127.0.0.1", "9600"); InitializationData localInitializationData = new InitializationData(); localInitializationData.properties = Util.createProperties(); localInitializationData.properties.setProperty("Ice.Default.Locator", str); ic = Util.initialize(localInitializationData); MessageServiceIcePrx messageclient = MessageServiceIcePrxHelper.checkedCast(ic.stringToProxy("messageService")); CalcServiceIcePrx calcclient = CalcServiceIcePrxHelper.checkedCast(ic.stringToProxy("calcService")); if (messageclient == null || calcclient == null ) throw new Error("Invalid proxy"); Map<String ,String > map = new HashMap<String, String>(); Message msg = new Message(MessageType.INFO, ActionType.Add,new int[]{1},map); System.out.println(messageclient.sendMessage(msg));//调用接口完成消息发送 System.out.println(calcclient.calc(12, 4, CalcType.Adds));//调用接口完成数学计算 } catch (Ice.LocalException e) { e.printStackTrace(); status = 1; } catch (Exception e) { System.err.println(e.getMessage()); status = 1; } if (ic != null) { try { ic.destroy(); } catch (Exception e) { System.err.println(e.getMessage()); status = 1; } } System.exit(status); } }
7,执行IceClient ,控制台输出
INFO Add [1]
16.0
到此调用成功,实例完成。