1.问题描述
在系统维护期间,当有request过来的时候,比较友好的做法是返回一个“现在系统正在维护,请稍候访问”的页面。
由于对每个request都要做这样的check,所以一般会有一个专门用来做check的方法,或者工具类。
系统维护期间,在一个xml文件里描述,为叙述方便叫outsideServiceTime.xml。xml文件的数据在系统启动的时候load进内存,
check方法从内存里读取数据,来做判断。
这种做法美中不足的是,当outsideServiceTime.xml内容被修改的时候,只有重启web应用程序,才能被反映进系统。
对于商业系统来说,重启系统通常是下策,不得已而为之则可。对于系统维护人员追加一个暂停服务的时间段就要重启,
实在是不划算。
能不能文件内容变更后,自动被load到内存呢?
答案是肯定的。
2.模式设计TS
Timer + Singleton
(1)Singleton工具类
对于这样的check,做成单例模式比较合适,唯一实例,唯一数据。唯一数据与文件内容保持一致。
方法和数据成员如下。
private 数据Object data;
private static 类名 self;
private 类名{} //Constructor
private static 类名 getInscnte(){
if (self != null) }
return self;
}
synchronized (类名.class) {
self = new 类名();
}
}
public static final void init(String fileName) {
self = getInstacne();
synchronized (类名.class) {
// load Data
self.data = loadData(fileName);
}
}
private static final 数据Object loadData(String fileName) {
数据Object ret = new 数据Object();
//ReadFile
ret.cola = xxxx;
//读取的结果作为对象返回
return ret;
}
以下几点说明
1)loadData方法把对象返回数据对象,所以如果由于文件格式被改恶,比如不小心把xml标签少写了一个字符,
因而读取失败,引发异常,这时候self.data复制尚未发生,所以不会影响上次成功load进来的数据。
2)init处理内部,因为要更新唯一数据,所以使用了synchronized,所以这个时候系统其他线程被设定为等待状态。
(2)Timer定时器
Singleton工具类启动和relaod的时间点为
1) 系统启动时
2) outsideServiceTime.xml文件被更新时
考虑到2),需要不断的check文件的变更日期lastModified(),所以加入定时器。
每隔一段时间比如10分钟,check一次文件的变更时间,如果比上次记录的大,记下时间,调用Singleton工具类的init方法,
从而实现数据的动态reload。
reload的时候,如果发生异常,要写进日志(log文件),以提醒系统管理员设定更新无效。
定时器的启动:
在ContextListener的contextInitialized方法里启动,然后把启动的Timer对象,保存到ServletContext。
定时器的终止:
在ContextListener的contextDestroyed方法,从ServletContext中取出被启动的Timer,执行cancel操作。
3.适用范围
Singleton单例模式,当实例对应的数据发生改变,需要动态reload的情况。
数据不光是本地文件,也可以是网络文件或者数据,比如内容定期把网络内容更新到本地。
数据也可以是数据库的内容,定期查询更新等等。
也可以是web服务,当不希望频繁的访问web服务,而是中间做缓存的时候。