SSH框架网上商城项目第15战之线程、定时器同步首页数据
上一节我们做完了首页ui界面,但是有个问题:如果我在后台添加了一个商品,那么我必须重启一下服务器才能重新同步后台数据,然后刷新首页才能同步数据。这明显不是我们想要的效果,一般这种网上商城首页肯定不是人为手动同步数据的,那么如何解决呢?我们需要用到线程和定时器来定时自动同步首页数据。
1. timer和timertask
我们需要用到timer和timertask两个类。先来介绍下这两个类。
timer是一种工具类,在java.util包中,线程用其安排以后在后台线程中执行的任务。可安排任务执行一次,或者定期重复执行。它有个构造函数:
timer(boolean isdaemon) //创建一个新计时器,可以指定其相关的线程作为守护程序运行。
守护线程即主线程结束后,该线程也结束,非守护线程即主线程结束后,该线程仍然继续执行。isdaemon为true时为守护线程。timer类有个schedule方法可以创建一个任务,如下:
void schedule(timertask task, date firsttime, long period) //安排指定的任务在指定的时间开始进行重复的固定延迟执行。 //第一个参数是指定任务,即timertask对象;第二个参数为第一次开启任务时间; 第三个参数为时间间隔,即每隔多长时间执行一次
我们再来看看timertask,timertask是用来创建一个新的线程任务的,它实现了runnable接口,如果我们要创建一个新的线程任务,只需要继承timertask,并重写run方法即可。
2. 创建一个新的线程任务
下面我们来创建一个新的线程任务,用来更新后台数据:
@component //把该对象交给spring管理 public class producttimertask extends timertask { @resource private productservice productservice = null; //注入productservice @resource private categoryservice categoryservice = null; //注入categoryservice private servletcontext application = null; //定义一个servletcontext对象,因为我们更新了后台数据后,需要存入application域里面 public void setapplication(servletcontext application) { this.application = application; //通过监听器将这个application对象set进来,因为这里是无法拿application对象的 } @override //和监听器在项目启动的时候数据初始化的逻辑一样 public void run() { system.out.println("----run----"); list<list<product>> biglist = new arraylist<list<product>>(); //biglist中存放一个装有category类的list // 1. 查询出热点类别 for(category category : categoryservice.querybyhot(true)) { //根据热点类别id获取推荐商品信息 list<product> lst = productservice.querbycategoryid(category.getid()); biglist.add(lst); //将装有category的list放到biglist中 } // 2. 把查询的biglist交给application内置对象 application.setattribute("biglist", biglist); //假设我们已经拿到了application对象 } }
接下来,我们修改项目启动时监听器里面的内容,原本上面的这个查询操作是放在监听器中,当项目启动时,监听器开始执行,获取后台数据,存到application域中,然后前台通过jstl标签从application域中拿到数据。现在我们把这些事情交给我们定义的producttimertask去做,那么监听器中只要设置一下定时器,让producttimertask定时去更新一下后台数据即可。看看监听器中修改后的代码:
3. 在监听器中启动定时器
//@component //监听器是web层的组件,它是tomcat实例化的,不是spring实例化的。不能放到spring中 public class initdatalistener implements servletcontextlistener { private producttimertask producttimertask = null; //定义一个producttimertask对象 private applicationcontext context = null; @override public void contextdestroyed(servletcontextevent event) { // todo auto-generated method stub } @override public void contextinitialized(servletcontextevent event) { context = webapplicationcontextutils.getwebapplicationcontext(event.getservletcontext()); producttimertask = (producttimertask) context.getbean("producttimertask");//从配置文件中获取producttimertask对象 //把内置对象交给producttimertask,因为producttimertask里面是拿不到application的,只能通过监听器set给它 producttimertask.setapplication(event.getservletcontext()); //通过设置定时器,让首页的数据每个一小时同步一次(配置为守护线程) new timer(true).schedule(producttimertask, 0, 1000*60*60);//每个一小时执行一次producttimertask任务,即更新一下后台数据 } }
关于initdatalistener监听器中原来的操作代码,可以对比上一节中的内容,其实就是producttimertask中的更新后台数据,只不过现在放到timertask中去做了而已。这样我们就完成了使用线程和定时器定期同步首页数据,这个时间间隔可以自己设定。
其实csdn博客里的部分首页数据也不是实时更新的,每天晚上会有个时间更新一次,例如左侧栏目中的博客排名,阅读排行后的显示的阅读量等,这些都是每天晚上更新一次,应该就是在后台设置了每天更新一次,原理跟这里应该是一样的。这样也减轻了服务器的压力。
本文链接:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: java、js中实现无限层级的树形结构方法(类似递归)
下一篇: 二叉搜索树(两个是否为同一个??)