本文接上篇博文《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实现数学计算:
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实现发送消息
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实现服务器端接口注册:
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", "default -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
## The IceGrid locator proxy.#Ice.Default.Locator=IceTestServiceGrid/Locator:tcp -p 10000
## IceGrid registry configuration.#IceGrid.Registry.Client.Endpoints=tcp -p 10000IceGrid.Registry.Server.Endpoints=tcpIceGrid.Registry.Internal.Endpoints=tcpIceGrid.Registry.Data=db/rescenter_registryIceGrid.Registry.PermissionsVerifier=IceTestServiceGrid/NullPermissionsVerifierIceGrid.Registry.AdminPermissionsVerifier=IceTestServiceGrid/NullPermissionsVerifierIceGrid.Registry.SSLPermissionsVerifier=IceTestServiceGrid/NullSSLPermissionsVerifierIceGrid.Registry.AdminSSLPermissionsVerifier=IceTestServiceGrid/NullSSLPermissionsVerifier
## Dummy username and password for icegridadmin.#IceGridAdmin.Username=fooIceGridAdmin.Password=bar
#set server active Connection ManagermentIce.ACM.Server=60## IceGrid node configuration.#
IceGrid.Node.Name=node1IceGrid.Node.Endpoints=tcpIceGrid.Node.Data=db/node1IceGrid.Node.CollocateRegistry=1
IceGrid.Node.Trace.Activator=1IceGrid.Node.Trace.Adapter=2IceGrid.Node.Trace.Server=3
根据需要在当前目录下创建db/node1,db/rescenter_registry文件夹
创建application.xml文件
<icegrid> <application name="icetest"> <server-template id="icetest-server-template"> <parameter name="index" /> <server id="rescenter_${index}" exe="C:/Program Files/Java/jdk1.6.0_10/bin/java" activation="on-demand"> <!---server -Xms128m -Xmx256m -d64 -XX:PermSize=128m--> <option>-classpath</option> <option>E:/workspace/ICEServer/bin</option> <option>-Djava.ext.dirs=E:/workspace/ICEServer/lib</option> <option>-server</option> <option>com.alan.ice.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::ice::MessageServiceIceImpl" /> <object identity="calcService" type="::com::alan::ice::CalcServiceIceImpl" /> </replica-group> <node name="node1"> <server-instance template="icetest-server-template" index="1" /> </node> </application>
</icegrid>
创建start_server.bat
path=%path%;E:/Ice-3.3.0/binicegridnode --Ice.Config=config-ice.grid --deploy application.xml pause
创建完成后就可以双击start_server.bat来启动服务了
6,创建客户端调用项目ICEClient,导入ice.jar以及前面生产的icetest.jar,在项目下创建IceClient .java
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" ,"localhost", "10000"); 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
到此调用成功,实例完成。