技术篇(4)--基于QPG容器的服务扩展
不好意思,这个月单位的事情实在太多。昨天又加班到23:00。
在技术篇(2)--QPG容器的高级用法中我们讲到,使用QPG平台后,您就可以把对象间的耦合和依赖降到最小。以前的做法如下:
原始法:
TypeA o1=new TypeA();//可能是算法策略
TypeB o2=new TypeB(o1);
o2.getResults(x,y);// may be call o1.getResults(x,y)
改进法:
TypeB o2=new TypeB("math1");//call 工厂建立TypeA实例
这种做法作后还是形成了对TypeA的间接依赖。
而使用SimpleContainer简单的方法:
DTO handle(string ServiceName,DTO data);
您就不用关心是哪个对象来完成您的服务要求,可能服务对象有很多个,有很多种类型,还可能分布在千里之外的另一台机器上。
那么,如何将一些常用的服务通过QPG平台集成起来呢?下面以email sender作为例子讲一下。为了简洁。我去掉了实际发送邮件的具体代码。
首先,为了让容器可以自动启动服务,我们需要实现IService和IStartable(Castle提供)接口:
using Castle.Model;
using QPG.Interface;
using QPG.Utility;
using QPG;
public class EmailSender : IService,IStartable{
}
IService 只要实现ServiceName属性和handle方法
IStartable只要实现Start和Stop方法,平台容器会自动调用它们,不用您老操心的了:-)
运作原理如下:
1) 服务者要从容器里获得消息队列实例;
2) 设置一个定时器定时从队列里取回自己要处理的请求并进行处理;
3) 为了及时响应,应该在启动时成为队列收到请求的处理监听者,这样才能收到消息。
具体代码如下:
public class EmailSender : IService,IStartable {
private bool _Started = false;
private bool _Stopped = false;
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
private System.Collections.Queue _queue = System.Collections.Queue.Synchronized(new Queue());
private string _serviceName="qpg.email_sender";
private BroadCastEventWrapper wrapper=null;
private System.Timers.Timer _timer;
private IMessageQueue _mq;
public EmailSender() {
_mq=SimpleContainer.MessageQueue;
_timer=new System.Timers.Timer(1000);
_timer.Elapsed+=new System.Timers.ElapsedEventHandler(timer_Elapsed);
![](/Images/OutliningIndicators/InBlock.gif)
}
public void attach(BroadCastEventHandler func) {
if(wrapper==null){
wrapper=new BroadCastEventWrapper();
wrapper.OnLocalBroadCast += new BroadCastEventHandler(func);
_mq.OnBroadCast+=new BroadCastEventHandler(wrapper.BroadCasting);
}
}
![](/Images/OutliningIndicators/InBlock.gif)
public void detach() {
_mq.OnBroadCast-=new BroadCastEventHandler(wrapper.BroadCasting);
}
public string ServiceName {
get{return _serviceName;}
}
![](/Images/OutliningIndicators/InBlock.gif)
public virtual void Start() {
if(_Started==true) return;
SimpleContainer.SysLogger.DEBUG("email_sender Started");
_timer.Enabled=true;
_Started=true;
attach(new QPG.Interface.BroadCastEventHandler(handle));
}
![](/Images/OutliningIndicators/InBlock.gif)
public virtual void Stop() {
SimpleContainer.SysLogger.DEBUG("email_sender Stopped");
_Stopped = true;
_timer.Enabled=false;
detach();
}
public virtual DTO handle(DTO data) {
_queue.Enqueue(data);
DTO rt=new DTO(data);
rt.setOutputData(new Parameter[]{new Parameter("Msg","Put msg to queue-->"+data.RequestArgs[0].Value.ToString())},null);
return rt;
}
protected virtual bool send(ParametersHelper ph) {
bool rt=true;
try{
// real sent by SMTP![](/Images/dot.gif)
![](/Images/dot.gif)
}
catch{rt=false;}
return rt;
}
![](/Images/OutliningIndicators/InBlock.gif)
private void getRequest() {
DTO d=_mq.receieveRequestFromQueue(ServiceName);
if(d!=null) {
d=handle(d);// 在这里没有多大意义,不用处理什么,只是返回一个通知,不让客户端等待
_mq.sendResultToQueue(d.TransactionID,d);
}
}
![](/Images/OutliningIndicators/InBlock.gif)
protected void run() {
getRequest();
if(_queue.Count<1) return;
DTO data=(DTO)_queue.Dequeue();
ParametersHelper ph=new ParametersHelper(data.RequestArgs);
SimpleContainer.SysLogger.DEBUG(ph.ToString());
if(send(ph)) SimpleContainer.SysLogger.DEBUG("OK!");
else SimpleContainer.SysLogger.DEBUG("FAIL!");
}
![](/Images/OutliningIndicators/InBlock.gif)
public virtual void handle(QPG.Utility.NotifyArgs arg) {
if(arg.RequestServiceName!=ServiceName) return;
run();
}
![](/Images/OutliningIndicators/InBlock.gif)
public virtual bool Started {
get { return _Started; }
}
![](/Images/OutliningIndicators/InBlock.gif)
public virtual bool Stopped {
get {
return _Stopped;
}
}
![](/Images/OutliningIndicators/InBlock.gif)
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
run();
![](/Images/OutliningIndicators/InBlock.gif)
}
}
今后您要做的是不断稳定现有的服务,增加新的服务。您会发现开发将会是一种享受了。。。。
在技术篇(2)--QPG容器的高级用法中我们讲到,使用QPG平台后,您就可以把对象间的耦合和依赖降到最小。以前的做法如下:
原始法:
TypeA o1=new TypeA();//可能是算法策略
TypeB o2=new TypeB(o1);
o2.getResults(x,y);// may be call o1.getResults(x,y)
改进法:
TypeB o2=new TypeB("math1");//call 工厂建立TypeA实例
这种做法作后还是形成了对TypeA的间接依赖。
而使用SimpleContainer简单的方法:
DTO handle(string ServiceName,DTO data);
您就不用关心是哪个对象来完成您的服务要求,可能服务对象有很多个,有很多种类型,还可能分布在千里之外的另一台机器上。
那么,如何将一些常用的服务通过QPG平台集成起来呢?下面以email sender作为例子讲一下。为了简洁。我去掉了实际发送邮件的具体代码。
首先,为了让容器可以自动启动服务,我们需要实现IService和IStartable(Castle提供)接口:
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
IService 只要实现ServiceName属性和handle方法
IStartable只要实现Start和Stop方法,平台容器会自动调用它们,不用您老操心的了:-)
运作原理如下:
1) 服务者要从容器里获得消息队列实例;
2) 设置一个定时器定时从队列里取回自己要处理的请求并进行处理;
3) 为了及时响应,应该在启动时成为队列收到请求的处理监听者,这样才能收到消息。
具体代码如下:
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/dot.gif)
![](/Images/dot.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
今后您要做的是不断稳定现有的服务,增加新的服务。您会发现开发将会是一种享受了。。。。