上一篇开发一个简单的HelloIce,利用Ice的API开发一个服务并将它启动起来,就像在J2EE中开发一个Servlet一样,目前在项目中,很少使用Servlet,直接用上层封装好的一些MVC框架,如SpringMVC、Struts2等来减少编码工作量并提升开发速度。IceBox则是等价于框架,可以只关注于业务代码的开发,而对于配置文件、服务启动、日志等程序必备的非业务相关的功能都已经实现。
IceBox就像一个Tomcat,写N个Ice服务的代码,用一个装配文件定义需要加载的服务列表、服务的启动参数、启动次序等必要信息,然后启动IceBox,应用系统就能够正常运行了。
一个IceBox内部会创建一个service manager对象(Ice.Admin),这个对象专门负责loading和initializing那些配置好了的服务,可以有选择性的将这些服务暴露给远程客户端,如IceBox或IceGrid的administrativeutilities,这样IceBox和IceGrid就可以执行某些远程管理任务。
要将一个Ice服务引入IceBox中,需要引入IceBox.jar这个库,另外服务的实现类继承IceBox定义的Service接口即可。start,stop方法。
IceBox定义的这个Service接口是一个标准的“服务生命周期”管理接口,其中的start方法可以等价于SpringFrameword中的Bean的init方法,在一个Bean的业务被调用之前,Spring会先调用其来初始化这个bean一样的逻辑。
IceBox demo
(1) 定义bookservice.slice文件
module book{
struct Message{
string name;
int type;
bool valid;
double price;
string content;
};
interface OnlineBook{
Message bookTick(Message msg);
};
};
(2) 实现服务端实现代码,实现IceBox的service接口。
package com.bookice;
import Ice.Communicator;
import Ice.Current;
import Ice.ObjectAdapter;
import IceBox.Service;
import book.Message;
import book._OnlineBookDisp;
public class OnlineBookImpl extends _OnlineBookDisp implements Service {
private ObjectAdapter _adapter;
@Override
public Message bookTick(Message msg, Current __current) {
System.out.println("BookTick to call. ");
System.out.println("booktick called: "+msg.content);
msg.content="JackTicket";
return msg;
}
@Override
public void start(String name, Communicator communicator, String[] args) {
// 创建adapter,
_adapter = communicator.createObjectAdapter(name);
// 创建servant
Ice.Object object = this;
_adapter.add(object, communicator.stringToIdentity(name));
_adapter.activate();
System.out.println(name +" started!!!");
}
@Override
public void stop() {
System.out.println(this._adapter.getName()+" stoped!!!");
_adapter.destroy();
}
}
// 日志输出可能更好
(3) 配置文件
config.properties
#service properties
IceBox.InstanceName=BookIceBox 1
IceBox.InheritProperties=1
IceBox.PrintServicesReady=MyAppIceBox 1
IceBox.ServiceManager.Endpoints=tcp -p 9999 -h localhost
#performance properties
Ice.ThreadPool.Server.Size=4
Ice.ThreadPool.Server.SizeMax=100
Ice.ThreadPool.Server.SizeWarn=40
Ice.ThreadPool.Client.Size=4
Ice.ThreadPool.Client.SizeMax=100
Ice.ThreadPool.Client.SizeWarn=40
#for system stronger
Ice.ACM.Client=300
Ice.ACM.Server=300
#log and trace
#Ice.LogFile=iceserver.log
Ice.PrintStackTraces=1
Ice.Trace.Retry=2
Ice.Trace.Network=2
Ice.Trace.ThreadPool=1
Ice.Warn.Connections=1
Ice.Warn.Dispatch=1
Ice.Warn.Endpoints=1
#service define begin
#IceBox.Service.name=entry_point [--key=value] [args]
# name is used in start(String name, Communicator communicator, String[] args) name
IceBox.Service.OnlineBookService=com.bookice.OnlineBookImpl prop1=1 prop2=2 prop3=3
#IceBox.Service.SMSService=com.SMSServiceI2
OnlineBookService.Endpoints=tcp -p 10001 -h localhost
#service end
#service load order
IceBox.LoadOrder=OnlineBookService
IceBox.UseSharedCommunicator.OnlineBookService=1
启动整个项目,console输出如下:
-- 17-8-17 13:55:49:170 IceBox.Server: ThreadPool: creating Ice.ThreadPool.Client: Size = 1, SizeMax = 1, SizeWarn = 0
-- 17-8-17 13:55:49:223 IceBox.Server: Network: attempting to bind to tcp socket 127.0.0.1:10001
-- 17-8-17 13:55:49:226 IceBox.Server: Network: listening for tcp connections at 127.0.0.1:10001
-- 17-8-17 13:55:49:232 IceBox.Server: ThreadPool: creating Ice.ThreadPool.Server: Size = 1, SizeMax = 1, SizeWarn = 0
-- 17-8-17 13:55:49:233 IceBox.Server: Network: published endpoints for object adapter `OnlineBookService':
tcp -h localhost -p 10001
-- 17-8-17 13:55:49:233 IceBox.Server: Network: accepting tcp connections at 127.0.0.1:10001
OnlineBookService started!!!
MyAppIceBox 1 ready
(4) OnlineBook Client代码
package com.bookice;
import book.Message;
import book.OnlineBookPrx;
import book.OnlineBookPrxHelper;
public class OnlineBookClient {
public static void main(String[] args) {
int status =0;
Ice.Communicator ic=null;
try{
//初始化Communicator连接对象,负责处理客户端的连接,可以进行设置,如客户端连接数量
ic = Ice.Util.initialize(args);
// 客户端代理proxy对象,访问确定的endpoints,返回的对象是广义的
Ice.ObjectPrx base = ic.stringToProxy("OnlineBookService:tcp -h localhost -p 10001");
// 类似于强制转换, 转换为具体的对象。
OnlineBookPrx onlineBookproxy = OnlineBookPrxHelper.checkedCast(base);
if(onlineBookproxy==null)
{
throw new Error("Invalid proxy");
}
// 实际上是调用服务器端的方法。
Message msg= new Message();
msg.name="MrWang";
msg.type=3;
msg.price=99;
msg.valid=true;
msg.content="aaaaaa";
Message retMsg = onlineBookproxy.bookTick(msg);
System.out.println(retMsg.content);
}catch(Exception e){
e.printStackTrace();
status=1;
}finally {
if (ic!= null){
ic.destroy();
}
}
System.exit(status);
}
}
运行过程:
server:
-- 17-8-17 13:55:49:233 IceBox.Server: Network: accepting tcp connections at 127.0.0.1:10001
OnlineBookService started!!!
MyAppIceBox 1 ready
-- 17-8-17 14:02:03:363 IceBox.Server: Network: accepted tcp connection
local address = 127.0.0.1:10001
remote address = 127.0.0.1:55173
-- 17-8-17 14:02:03:378 IceBox.Server: Network: tcp connection established
local address = 127.0.0.1:10001
remote address = 127.0.0.1:55173
BookTick to call.
booktick called: aaaaaa
-- 17-8-17 14:02:03:398 IceBox.Server: Network: closing tcp connection
local address = 127.0.0.1:10001
remote address = 127.0.0.1:55173
Client
JackTicket
(5) 运行过程图片
很明显的就是没有了Server端,server在Impl代码中实现了,同样,上面的只有一个Ice服务,没有体现IceBox的优势,下篇解释