日期:2014-05-16  浏览次数:20511 次

用Listener+Timer实现自动周期更新数据库

??? 前段时间在做一个维护升级一个基于SSI的网站项目,叫做《网络课堂系统》,是广州市一所专科学院在使用的。这个项目是我所在的学院开发工作室两三年前接回来的项目,所以也经过了两三个年级的师兄的手最终传到我们手上。可想而知,这个项目的原代码已经非常凌乱了。原来打算直接重构整个项目的,但由于这是个正在使用中的项目,而我们又人手有限,那所学院的负责人Y要求我们先进行维护升级以满足使用需要后再考虑重构的事情。

??? 这个项目的数据库有一张学期表,用来记录学期信息,并用一个字段指定哪个是当前学期。但是这张学期表的数据更新居然是靠手动修改数据库实现的,对于用户来说,这非常的不人性化,因此我得到了一个任务:实现一个操作简单的功能以代替这种非常不人性化的操作。

??? 由于开发经验还不够等原因,我一开始是从管理员的方向去想。首先,我想在管理员页面添加一个按钮,当管理员点击这个按钮的时候进行检查更新数据库学期表。但是Y和我说管理员可能忘记点击,所以这个想法作罢。接着,我想写一个filter用来过滤登录信息,如果发现是管理员登录的话就检查更新数据库学期表。可是,这个想法还是没有实现,原因有二:一是Y说管理员不一定会在开学前登录一次,这可能会导致学期表没及时更新;二是我那时我发现无法用Spring对filter进行注入,实现起来要多走很多路。最后,我打算写一个Listener实现自动周期更新学期表。

?

??? 后来经过测试,发现Spring也无法通过一般途径对Listener进行注入,查了相关资料发现这是因为filter、listener、servlet不由Spring管理。虽然麻烦,但我也决定做下去了。

当然,在实现的过程中,我也有不断的google查资料,并不是完全靠自己想出来的。

?

??? 先来简单的介绍一下listener:listener是servlet监听器,它可以监听客户端的请求、服务端的操作等。要创建一个listener就必须实现相关的接口,这类接口有四个:ServletContextAttributeListener、ServletContextListener、HttpSessionAttributeListener、HttpSessionListener。

?

ServletContestener监听对ServletContext属性的操作,比如增删查改等。(ServletContext是servlet上下文的意思,整个web项目共享同一个ServletContext)

?

ServletContextListener用来监听ServletContext,而并非监听对ServletContext属性的操作。它有两个方法:当创建ServletContext时,调用contextInitialized (ServletContextEvent sce)方法;当销毁ServletContext时,调用contextDestroyed(ServletContextEvent sce)方法。

?

HttpSessionAttributeListener用来监听HttpSession中的属性的操作。它有三个方法:当在Session增加一个属性时,调用attributeAdded (HttpSessionBindingEvent se) 方法;当在Session删除一个属性时,调用attributeRemove(HttpSessionBindingEvent se)方法;当在Session属性被重新设置时,调用attributeReplaced(HttpSessionBindingEvent se) 方法。

?

?

HttpSessionListener 监听HttpSession的操作。有两个方法:当创建一个Session时,调用session Created(HttpSessionEvent se)方法;当销毁一个Session时,调用sessionDestroyed (HttpSessionEvent se)方法。

?

??? 要实现我想实现的那个功能的话,就要写一个实现了ServletContextListener的Listener。

package com.course.online.listener;

import java.util.Timer;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import com.course.online.util.UpdateTerm;

public class TermListener implements ServletContextListener{
	
	private Timer timer = null;
		
	public void contextDestroyed(ServletContextEvent scEvent) {
		// TODO Auto-generated method stub
		timer.cancel();
		System.out.println("停止学期更新!");
	}

	
	public void contextInitialized(ServletContextEvent scEvent) {
		// TODO Auto-generated method stub
		timer = new Timer(true);
		/*24*60*60*1000*/
		timer.schedule(new UpdateTerm(), 5000, 24*60*60*1000);
		System.out.println("开始监听学期更新!");
	}

}

?

??? 先看一上面这篇Listener的代码,里面用到了一个Timer对象。这个Timer对象的作用是实现每相隔一段时间就执行某个操作一次。

?

??? 当开始运行项目,ServletContext被创建时服务器调用contextInitialized(ServletContextEvent scEvent) 方法,生成一个Timer对象,并调用该对象的schedule(new UpdateTerm(), 5000, 24*60*60*1000)方法,其中参数“new UpdateTerm()”代表要定时执行的操作,“5000”代表第一次执行的时间为第5秒,“24*60*60*1000”代表执行周期时间为一天。

?

??? 当项目结束运行,ServletContext被销毁的时候,服务器调用contextDestroyed(ServletContextEvent scEvent) 方法,该方法调用Timer对象的cancl()方法销毁Timer对象。

?

?? 接着看一下UpdateTerm.java的代码,UpdateTerm.java是用来执行数据库更新的关键操作的:

package com.course.o