【SSH网上商城项目实战15】线程、定时器同步首页数据(类似于CSDN博客定期更新排名)

转载 2017年01月12日 18:11:55

        上一节我们做完了首页UI界面,但是有个问题:如果我在后台添加了一个商品,那么我必须重启一下服务器才能重新同步后台数据,然后刷新首页才能同步数据。这明显不是我们想要的效果,一般这种网上商城首页肯定不是人为手动同步数据的,那么如何解决呢?我们需要用到线程和定时器来定时自动同步首页数据。

1. Timer和TimerTask

        我们需要用到Timer和TimerTask两个类。先来介绍下这两个类。

        Timer是一种工具类,在Java.util包中,线程用其安排以后在后台线程中执行的任务。可安排任务执行一次,或者定期重复执行。它有个构造函数:

  1. Timer(boolean isDaemon)  
  2. //创建一个新计时器,可以指定其相关的线程作为守护程序运行。  
Timer(boolean isDaemon)
//创建一个新计时器,可以指定其相关的线程作为守护程序运行。
        守护线程即主线程结束后,该线程也结束,非守护线程即主线程结束后,该线程仍然继续执行。isDaemon为true时为守护线程。Timer类有个schedule方法可以创建一个任务,如下:

  1. void  schedule(TimerTask task, Date firstTime, long period)   
  2. //安排指定的任务在指定的时间开始进行重复的固定延迟执行。  
  3. //第一个参数是指定任务,即TimerTask对象;第二个参数为第一次开启任务时间;第三个参数为时间间隔,即每隔多长时间执行一次  
void  schedule(TimerTask task, Date firstTime, long period) 
//安排指定的任务在指定的时间开始进行重复的固定延迟执行。
//第一个参数是指定任务,即TimerTask对象;第二个参数为第一次开启任务时间;第三个参数为时间间隔,即每隔多长时间执行一次
        我们再来看看TimerTask,TimerTask是用来创建一个新的线程任务的,它实现了Runnable接口,如果我们要创建一个新的线程任务,只需要继承TimerTask,并重写run方法即可。

2. 创建一个新的线程任务

        下面我们来创建一个新的线程任务,用来更新后台数据:

  1. @Component //把该对象交给Spring管理  
  2. public class ProductTimerTask extends TimerTask {  
  3.       
  4.     @Resource  
  5.     private ProductService productService = null//注入productService  
  6.     @Resource  
  7.     private CategoryService categoryService = null//注入categoryService  
  8.       
  9.     private ServletContext application = null//定义一个ServletContext对象,因为我们更新了后台数据后,需要存入application域里面  
  10.       
  11.     public void setApplication(ServletContext application) {  
  12.         this.application = application; //通过监听器将这个application对象set进来,因为这里是无法拿application对象的  
  13.     }  
  14.       
  15.     @Override  
  16.      //和监听器在项目启动的时候数据初始化的逻辑一样  
  17.     public void run() {  
  18.         System.out.println(”—-run—-“);  
  19.         List<List<Product>> bigList = new ArrayList<List<Product>>(); //bigList中存放一个装有Category类的list  
  20.          // 1. 查询出热点类别  
  21.         for(Category category : categoryService.queryByHot(true)) {  
  22.             //根据热点类别id获取推荐商品信息  
  23.             List<Product> lst = productService.querByCategoryId(category.getId());  
  24.             bigList.add(lst); //将装有category的list放到bigList中  
  25.         }  
  26.          // 2. 把查询的bigList交给application内置对象  
  27.          application.setAttribute(”bigList”, bigList); //假设我们已经拿到了application对象  
  28.     }  
  29.   
  30. }  
@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. 在监听器中启动定时器

  1. //@Component //监听器是web层的组件,它是tomcat实例化的,不是Spring实例化的。不能放到Spring中  
  2. public class InitDataListener implements ServletContextListener {  
  3.       
  4.     private ProductTimerTask productTimerTask = null//定义一个ProductTimerTask对象  
  5.     private ApplicationContext context = null;  
  6.       
  7.     @Override  
  8.     public void contextDestroyed(ServletContextEvent event) {  
  9.         // TODO Auto-generated method stub  
  10.   
  11.     }  
  12.   
  13.     @Override  
  14.     public void contextInitialized(ServletContextEvent event) {  
  15.   
  16.         context = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());                 
  17.         productTimerTask = (ProductTimerTask) context.getBean(”productTimerTask”);//从配置文件中获取ProductTimerTask对象  
  18.   
  19.         //把内置对象交给productTimerTask,因为productTimerTask里面是拿不到application的,只能通过监听器set给它  
  20.         productTimerTask.setApplication(event.getServletContext());  
  21.   
  22.         //通过设置定时器,让首页的数据每个一小时同步一次(配置为守护线程)  
  23.         new Timer(true).schedule(productTimerTask, 01000*60*60);//每个一小时执行一次productTimerTask任务,即更新一下后台数据  
  24.     }  
  25.   
  26. }  
//@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博客里的部分首页数据也不是实时更新的,每天晚上会有个时间更新一次,例如左侧栏目中的博客排名,阅读排行后的显示的阅读量等,这些都是每天晚上更新一次,应该就是在后台设置了每天更新一次,原理跟这里应该是一样的。这样也减轻了服务器的压力。


        相关阅读:http://blog.csdn.net/column/details/str2hiberspring.html

        整个项目的源码下载地址:http://blog.csdn.NET/eson_15/article/details/51479994

_____________________________________________________________________________________________________________________________________________________

—–乐于分享,共同进步!

—–更多文章请看:http://blog.csdn.net/eson_15
document.getElementById("bdshell_js").src = "http://bdimg.share.baidu.com/static/js/shell_v2.js?cdnversion=" + Math.ceil(new Date()/3600000)
    <div id="digg" articleid="51387378">
        <dl id="btnDigg" class="digg digg_enable" onclick="btndigga();">

             <dt>顶</dt>
            <dd>5</dd>
        </dl>


        <dl id="btnBury" class="digg digg_enable" onclick="btnburya();">

              <dt>踩</dt>
            <dd>0</dd>               
        </dl>

    </div>
 <div class="tracking-ad" data-mod="popu_222"><a href="javascript:void(0);" target="_blank">&nbsp;</a>   </div>
<div class="tracking-ad" data-mod="popu_223"> <a href="javascript:void(0);" target="_blank">&nbsp;</a></div>
<script type="text/javascript">
            function btndigga() {
                $(".tracking-ad[data-mod='popu_222'] a").click();
            }
            function btnburya() {
                $(".tracking-ad[data-mod='popu_223'] a").click();
            }
        </script>

<div style="clear:both; height:10px;"></div>


    <div class="similar_article" style="">
            <h4>我的同类文章</h4>
            <div class="similar_c" style="margin:20px 0px 0px 0px">
                <div class="similar_c_t">
                            <label class="similar_cur">
                                <span style="cursor:pointer" onclick="GetCategoryArticles('6214186','eson_15','foot','51387378');">------【SSH网上商城】<em>(29)</em></span>
                            </label>
                            <label class="">
                                <span style="cursor:pointer" onclick="GetCategoryArticles('6228419','eson_15','foot','51387378');">●  项目实战<em>(29)</em></span>
                            </label>
                </div>

                <div class="similar_wrap tracking-ad" data-mod="popu_141" style="max-height:195px;">
                    <a href="http://blog.csdn.net" style="display:none" target="_blank">http://blog.csdn.net</a>
                    <ul class="similar_list fl"><li><em>•</em><a href="http://blog.csdn.net/eson_15/article/details/51506334" id="foot_aritcle_51506334undefined5925793815918674" target="_blank" title="【SSH网上商城项目实战29】使用JsChart技术在后台显示商品销售报表">【SSH网上商城项目实战29】使用JsChart技术在后台显示商品销售报表</a><span>2016-05-26</span><label><i>阅读</i><b>6059</b></label></li> <li><em>•</em><a href="http://blog.csdn.net/eson_15/article/details/51484247" id="foot_aritcle_51484247undefined4446019075613674" target="_blank" title="【SSH网上商城项目实战27】域名空间的申请和项目的部署及发布">【SSH网上商城项目实战27】域名空间的申请和项目的部署及发布</a><span>2016-05-23</span><label><i>阅读</i><b>13823</b></label></li> <li><em>•</em><a href="http://blog.csdn.net/eson_15/article/details/51475431" id="foot_aritcle_51475431undefined232457073527782" target="_blank" title="【SSH网上商城项目实战26】完成订单支付后的短信发送功能">【SSH网上商城项目实战26】完成订单支付后的短信发送功能</a><span>2016-05-22</span><label><i>阅读</i><b>4705</b></label></li> <li><em>•</em><a href="http://blog.csdn.net/eson_15/article/details/51465067" id="foot_aritcle_51465067undefined359978016558673" target="_blank" title="【SSH网上商城项目实战24】Struts2中如何处理多个Model请求">【SSH网上商城项目实战24】Struts2中如何处理多个Model请求</a><span>2016-05-21</span><label><i>阅读</i><b>4245</b></label></li> <li><em>•</em><a href="http://blog.csdn.net/eson_15/article/details/51452243" id="foot_aritcle_51452243undefined2699218719809935" target="_blank" title="【SSH网上商城项目实战22】获取银行图标以及支付页面的显示">【SSH网上商城项目实战22】获取银行图标以及支付页面的显示</a><span>2016-05-19</span><label><i>阅读</i><b>3742</b></label></li> <li><em>•</em><a href="http://blog.csdn.net/eson_15/article/details/51441431" id="foot_aritcle_51441431undefined7846194646600373" target="_blank" title="【SSH网上商城项目实战20】在线支付平台的介绍">【SSH网上商城项目实战20】在线支付平台的介绍</a><span>2016-05-18</span><label><i>阅读</i><b>4107</b></label></li> </ul>

                    <ul class="similar_list fr"><li><em>•</em><a href="http://blog.csdn.net/eson_15/article/details/51487323" id="foot_aritcle_51487323undefined39863120367400184" target="_blank" title="【SSH网上商城项目实战28】使用Ajax技术局部更新商品数量和总价">【SSH网上商城项目实战28】使用Ajax技术局部更新商品数量和总价</a><span>2016-05-24</span><label><i>阅读</i><b>5338</b></label></li> <li><em>•</em><a href="http://blog.csdn.net/eson_15/article/details/51479994" id="foot_aritcle_51479994undefined02484285753117077" target="_blank" title="【SSH网上商城项目实战30】项目总结(附源码下载地址)">【SSH网上商城项目实战30】项目总结(附源码下载地址)</a><span>2016-05-27</span><label><i>阅读</i><b>21892</b></label></li> <li><em>•</em><a href="http://blog.csdn.net/eson_15/article/details/51475046" id="foot_aritcle_51475046undefined062401490199214926" target="_blank" title="【SSH网上商城项目实战25】使用java email给用户发送邮件">【SSH网上商城项目实战25】使用java email给用户发送邮件</a><span>2016-05-22</span><label><i>阅读</i><b>4008</b></label></li> <li><em>•</em><a href="http://blog.csdn.net/eson_15/article/details/51464415" id="foot_aritcle_51464415undefined8632468675428662" target="_blank" title="【SSH网上商城项目实战23】完成在线支付功能">【SSH网上商城项目实战23】完成在线支付功能</a><span>2016-05-20</span><label><i>阅读</i><b>8822</b></label></li> <li><em>•</em><a href="http://blog.csdn.net/eson_15/article/details/51447492" id="foot_aritcle_51447492undefined6672598436126573" target="_blank" title="【SSH网上商城项目实战21】从Demo中看易宝支付的流程">【SSH网上商城项目实战21】从Demo中看易宝支付的流程</a><span>2016-05-18</span><label><i>阅读</i><b>9655</b></label></li> </ul>
                <a href="http://blog.csdn.net/eson_15/article/category/6214186" class="MoreArticle">更多文章</a></div>
            </div>
        </div>    
<script type="text/javascript">
    $(function () {
        GetCategoryArticles('6214186', 'eson_15','foot','51387378');
    });
</script>

相关文章推荐

【SSH网上商城项目实战16】Hibernate的二级缓存处理首页的热门显示

网上商城首页都有热门商品,那么这些商品的点击率是很高的,当用户点击某个热门商品后需要进入商品的详细信息页面,就像淘宝里面那样。那么每次点击都要去后台查询一下该商品的详细信息,就会发送相应的sql语句,...

【SSH网上商城项目实战14】商城首页UI的设计

目录(?)[+]首页商品显示逻辑创建InitDataListener获取首页数据 首页UI页面设计        前面我们利用EasyUI和SSH搭建好了后台的基本框架,做好了后台的基本功能,包括对商...

【SSH网上商城项目实战06】基于DataGrid的数据显示

EasyUI中DataGrid以表格形式展示数据,并提供了丰富的选择、排序、分组和编辑数据的功能支持。DataGrid的设计用于缩短开发时间,并且使开发人员不需要具备特定的知识。它是轻量级的且功能丰富...
  • eson_15
  • eson_15
  • 2016年05月08日 15:25
  • 6730

【SSH网上商城项目实战09】添加和更新商品类别功能的实现

目录(?)[+]添加商品类别 1 添加类别的UI设计2 添加类别的逻辑实现更新商品类别1 更新类别的UI设计2 更新类别的逻辑实现         上一节我们做完了查询和删除商品的功能,这一节我们做一...

【SSH网上商城项目实战12】添加和更新商品功能的实现

添加商品部分原理和添加商品类别是一样的,不过要比商品类别复杂,因为商品的属性有很多,对应的数据库中的字段也就多了,添加商品还有个选项是上传图片,这一小块内容会在下一篇博客中单独说明,因为这涉及到一个知...
  • eson_15
  • eson_15
  • 2016年05月13日 09:41
  • 14574

【SSH网上商城项目实战28】使用Ajax技术局部更新商品数量和总价

在没有Ajax之前,一般都是根据用户修改的值去找Action,然后返回新的jsp页面重新加载整个页面,完成数字的更新。但是有了Ajax技术后,我们可以利用Ajax技术局部刷新要改变的地方,而不是重新加...
  • eson_15
  • eson_15
  • 2016年05月24日 18:07
  • 9311

【SSH网上商城项目实战03】使用EasyUI搭建后台页面框架

前面两节,我们整合了SSH并且抽取了service和action部分的接口,可以说基本开发环境已经搭建好了,这一节我们搭建一下后台的页面。我们讨论一下两种搭建方式:基于frameset和基于easyU...
  • eson_15
  • eson_15
  • 2016年05月07日 00:21
  • 15756

【SSH网上商城项目实战20】在线支付平台的介绍

之前已经完成了首页的显示,用户添加购物车,确认订单等功能,下面就是支付功能的开发了。用户确认了订单后会直接跳转到支付页面进行在线支付,在线支付需要第三方的接口,这一节主要介绍一些关于第三方支付的内容,...
  • eson_15
  • eson_15
  • 2016年05月18日 16:21
  • 7683

【SSH网上商城项目实战17】购物车基本功能的实现

上一节我们将商品的详细页面做完了,并使用了Hibernate的二级缓存加载详细页面来提高系统的性能。这节我们开始做购物车部分。 1. 添加新的表         首先我们向数据库中添加几张表:用户表、...
  • eson_15
  • eson_15
  • 2016年05月16日 14:25
  • 23635

【SSH网上商城项目实战17】购物车基本功能的实现

上一节我们将商品的详细页面做完了,并使用了hibernate的二级缓存加载详细页面来提高系统的性能。这节我们开始做购物车部分。 1. 添加新的表         首先我们向数据库中添加几张...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【SSH网上商城项目实战15】线程、定时器同步首页数据(类似于CSDN博客定期更新排名)
举报原因:
原因补充:

(最多只允许输入30个字)