【SSH網上商城專案實戰15】執行緒、定時器同步首頁資料(類似於部落格定期更新排名)
轉自:https://blog.csdn.net/eson_15/article/details/51387378
上一節我們做完了首頁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. 建立一個新的執行緒任務
下面我們來建立一個新的執行緒任務,用來更新後臺資料:
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 }
接下來,我們修改專案啟動時監聽器裡面的內容,原本上面的這個查詢操作是放在監聽器中,當專案啟動時,監聽器開始執行,獲取後臺資料,存到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, 0, 1000*60*60);//每個一小時執行一次productTimerTask任務,即更新一下後臺資料 24 } 25 26 }
關於InitDataListener監聽器中原來的操作程式碼,可以對比上一節中的內容,其實就是ProductTimerTask中的更新後臺資料,只不過現在放到TimerTask中去做了而已。這樣我們就完成了使用執行緒和定時器定期同步首頁資料,這個時間間隔可以自己設定。
其實CSDN部落格裡的部分首頁資料也不是實時更新的,每天晚上會有個時間更新一次,例如左側欄目中的部落格排名,閱讀排行後的顯示的閱讀量等,這些都是每天晚上更新一次,應該就是在後臺設定了每天更新一次,原理跟這裡應該是一樣的。這樣也減輕了伺服器的壓力。
轉自:https://blog.csdn.net/eson_15/article/details/51387378
上一節我們做完了首頁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. 建立一個新的執行緒任務
下面我們來建立一個新的執行緒任務,用來更新後臺資料:
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 }
接下來,我們修改專案啟動時監聽器裡面的內容,原本上面的這個查詢操作是放在監聽器中,當專案啟動時,監聽器開始執行,獲取後臺資料,存到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, 0, 1000*60*60);//每個一小時執行一次productTimerTask任務,即更新一下後臺資料 24 } 25 26 }
關於InitDataListener監聽器中原來的操作程式碼,可以對比上一節中的內容,其實就是ProductTimerTask中的更新後臺資料,只不過現在放到TimerTask中去做了而已。這樣我們就完成了使用執行緒和定時器定期同步首頁資料,這個時間間隔可以自己設定。
其實CSDN部落格裡的部分首頁資料也不是實時更新的,每天晚上會有個時間更新一次,例如左側欄目中的部落格排名,閱讀排行後的顯示的閱讀量等,這些都是每天晚上更新一次,應該就是在後臺設定了每天更新一次,原理跟這裡應該是一樣的。這樣也減輕了伺服器的壓力。