1、需求:java
項目上有時須要執行一些定時任務,好比:超過2天未處理的問題,郵件自動通知客服、對接人;3天未處理的問題,郵件自動通知客服、對接人和項目經理,同時標爲‘緊急’狀態;5天未處理的問題,郵件自動通知客服、對接人和項目經理,同時標爲‘很是緊急’狀態;mysql
這類定時任務能夠用簡單的JAVA實現。web
2、SQL準備:sql
1. 首先確定是要先查詢出超時的記錄,這裏須要用到MYSQL的一個數據庫自帶的函數TIMESTAMPDIFF,計算時間差很是方便:數據庫
語法:tomcat
TIMESTAMPDIFF(interval,datetime_expr1,datetime_expr2)ide
返回日期或日期時間表達式datetime_expr1 和datetime_expr2the 之間的整數差。其結果的單位由interval 參數給出。該參數必須是如下值的其中一個:函數
FRAC_SECOND。表示間隔是毫秒this
SECOND。秒spa
MINUTE。分鐘
HOUR。小時
DAY。天
WEEK。星期
MONTH。月
QUARTER。季度
YEAR。年
例1:
mysql> select TIMESTAMPDIFF(day,'2012-08-24','2012-08-30');
+----------------------------------------------+
| TIMESTAMPDIFF(day,'2012-08-24','2012-08-30') |
+----------------------------------------------+
| 6 |
+----------------------------------------------+
1 row in set (0.00 sec)
因此你的SQL的where後面跟的條件就能夠這樣使用: 超過3天但未過5天的記錄:
select xxx from xxx where xxx and TIMESTAMPDIFF(day,q.c_createtime,now()) > 3 and TIMESTAMPDIFF(day,q.c_createtime,now()) < 5
3、java中定時任務的實現:
方式有兩種,一種是:java.util.TimerTask ;一種是:java.util.concurrent.ScheduledExecutorService
網上能夠找到相關的使用方法:這裏使用第一種方式:
import java.util.Date; import java.util.Timer; import java.util.TimerTask; public class TimeTaskDemo2 { /** * 定時任務實現方式二 */ public static void main(String[] args) { // TODO Auto-generated method stub TimerTask task = new TimerTask() { @Override public void run() { // TODO Auto-generated method stub System.out.println("This is a time task ..."); } }; Timer timer = new Timer(); //task - 所要安排的任務。 delay - 執行任務前的延遲時間,單位是毫秒。 period - 執行各後續任務之間的時間間隔,單位是毫秒。 timer.scheduleAtFixedRate(task, 10*1000, 3*1000);
4、在WEB項目中實現
1. 定義個Listener類,繼承ServletContextListener;這個類會在tomcat啓動後自動加載;
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.Timer; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; public class StartTimerListener implements ServletContextListener{ Timer timer = new Timer(); //建立一個初始化監聽器對象,通常由容器調用 public StartTimerListener() { super(); // TODO Auto-generated constructor stub } @Override public void contextDestroyed(ServletContextEvent arg0) { // TODO Auto-generated method stub timer.cancel(); } //讓Web程序運行的時候自動加載Timer @Override public void contextInitialized(ServletContextEvent arg0) { // TODO Auto-generated method stub System.out.println("-------------StartTimerListener.init-------------"); timer.schedule(new TimerTaskAction(), getTomorrowDate(),24*3600*1000); } //獲取當前日期後一天的時間 public Date getTomorrowDate(){ Calendar c = Calendar.getInstance(); Date datetime=new Date(); Date morningtime=new Date(); SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd"); SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); c.setTime(datetime); int day = c.get(Calendar.DATE); //當前日期後一天,由於定時器的第三個參數是時間間隔,爲保證天天8天執行,不能讓開始時間是過去的時間 c.set(Calendar.DATE, day+1); try { morningtime = sdf2.parse(sdf1.format(c.getTime())+" 08:00:00"); } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } return morningtime; } /*public static void main(String args[]){ SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println(sdf2.format(getTomorrowDate())); }*/ }
2. 將這個Linstener在web.xml中註冊才能生效
<listener> <listener-class>com.crm.action.StartTimerListener</listener-class> </listener>
3. 定時器實現
1 import java.sql.ResultSet; 2 import java.sql.SQLException; 3 import java.util.ArrayList; 4 import java.util.List; 5 import java.util.TimerTask; 6 7 import com.crm.action.param.QuestionFollowDTO; 8 import com.crm.dao.BaseDao; 9 import com.crm.util.SendMailThread; 10 11 public class TimerTaskAction extends TimerTask{ 12 13 @Override 14 public void run() { 15 // TODO Auto-generated method stub 16 // System.out.println("this is a timer task..."); 17 /*List<QuestionFollowDTO> list = getResult(queryTimerOutQues(33)); 18 updateQuesLevel(list); 19 sendMailWarn(list,33);*/ 20 //超過2未超過3天 21 List<QuestionFollowDTO> outTwoDays = getResult(queryTimerOutQues(2)); 22 updateQuesLevel(outTwoDays); 23 sendMailWarn(outTwoDays,2); 24 25 //超過3天未過5天 26 List<QuestionFollowDTO> outThreeDays = getResult(queryTimerOutQues(3)); 27 updateQuesLevel(outThreeDays); 28 sendMailWarn(outThreeDays,3); 29 30 //超過5天 31 List<QuestionFollowDTO> outFiveDays = getResult(queryTimerOutQues(5)); 32 updateQuesLevel(outFiveDays); 33 sendMailWarn(outFiveDays,5); 34 } 35 36 //查詢超過day天未處理的問題 37 public ResultSet queryTimerOutQues(int days){ 38 String sql = " xxx " ; 39 switch(days){ 40 case 2: 41 sql += " and TIMESTAMPDIFF(day,q.createtime,now()) > 2 and TIMESTAMPDIFF(day,q.createtime,now()) <3 " ; 42 break; 43 case 3: 44 sql += " and TIMESTAMPDIFF(day,q.createtime,now()) > 3 and TIMESTAMPDIFF(day,q.createtime,now()) <5 " ; 45 break; 46 case 5: 47 sql += " and TIMESTAMPDIFF(day,q.createtime,now()) > 5 " ; 48 break; 49 case 33: //調試 50 sql += " and TIMESTAMPDIFF(day,q.createtime,now()) > 33 " ; 51 } 52 sql += " order by c_id desc " ; 53 54 // System.out.println("查詢問題SQL="+sql); 55 56 ResultSet rs = BaseDao.executeQuerySQL(null, sql, null); 57 58 return rs ; 59 } 60 61 public List<QuestionFollowDTO> getResult(ResultSet rs){ 62 List<QuestionFollowDTO> list = new ArrayList<QuestionFollowDTO>(); 63 try { 64 while(rs.next()){ 65 QuestionFollowDTO dto = new QuestionFollowDTO(); 66 dto.setQuesId(rs.getInt("c_id")); 67 dto.setQuesStatus(rs.getInt("c_status")); 68 dto.setQuesCreatetime(rs.getString("c_createtime")); 69 dto.setFromUserId(rs.getInt("c_user_id")); 70 dto.setFromUserName(rs.getString("fromUserName")); 71 dto.setFromUserMail(rs.getString("fromUserMail")) ; 72 dto.setNextUserId(rs.getInt("c_next_user")) ; 73 dto.setNextUserName(rs.getString("nextUserName")); 74 dto.setNextUserMail(rs.getString("nextUserMail")); 75 dto.setQuesTitle(rs.getString("c_title")); 76 77 list.add(dto); 78 } 79 } catch (SQLException e) { 80 // TODO Auto-generated catch block 81 e.printStackTrace(); 82 } 83 84 return list ; 85 } 86 87 /* 88 * list 超期問題數據 89 * level 緊急程度:遞增更新 90 */ 91 public void updateQuesLevel(List<QuestionFollowDTO> list){ 92 if(list!=null && list.size()>0){ 93 int length = list.size(); 94 String querIds = ""; 95 for(int i=0;i<length;i++){ 96 querIds += list.get(i).getQuesId() + ","; 97 } 98 99 String sql = " update question set c_level = c_level+1 where isvalid=true and level!=3 and c_id in ( " + querIds.substring(0, querIds.lastIndexOf(",")) + " ) " ; 100 System.out.println("更新問題LEVEL:"+sql); //緊急程度遞增 101 102 BaseDao.executeUpdateSQL(null, sql, null); 103 } 104 } 105 106 /* 107 * 發送郵件提醒 108 * list 超時的問題 109 * days 超時天數 110 */ 111 public void sendMailWarn(List<QuestionFollowDTO> list,int days){ 112 if(list!=null && list.size()>0){ 113 for(int i=0;i<list.size();i++){ 114 String mailAdrs = "" ; //郵箱通知 115 String managerMailAdr = "" ; //郵箱通知項目經理 116 String fmail = list.get(i).getFromUserMail(); 117 String nmail = list.get(i).getNextUserMail() ; 118 mailAdrs += ((fmail==null || fmail.trim().equals("") ? "" : fmail+"," ) + (nmail==null || nmail.trim().equals("") ? "" : nmail ) ) ; 119 if(days>=3){ //超過3天的通知項目經理 120 String sql = " select c_email from user where c_isvalid=true and c_roleid = 12 " ; // 查詢項目經理郵箱,提醒項目經理: 121 ResultSet rs = BaseDao.executeQuerySQL(null, sql, null); 122 try { 123 while(rs.next()){ 124 managerMailAdr += (rs.getString("c_email") + ","); 125 } 126 } catch (SQLException e) { 127 // TODO Auto-generated catch block 128 e.printStackTrace(); 129 } 130 } 131 // System.out.println("郵件通知地址:"+mailAdrs); 132 String mailContent = list.get(i).getQuesTitle(); 133 SendMailThread send = new SendMailThread(mailAdrs,"[系統提示:]您有一個問題超過"+days+"天未處理,請及時登陸CRM查看處理!","問題標題:"+mailContent); 134 //send.start(); 135 if(managerMailAdr.length()>0){ 136 // System.out.println("項目經理通知地址:"+managerMailAdr); 137 new SendMailThread(managerMailAdr,"[系統提示:CRM中有一個問題超過"+days+"天未處理]","問題標題:"+mailContent).start(); 138 } 139 } 140 } 141 } 142 }
上面代碼中發送郵件有用到另外的一個類,羣發郵件能夠參考前面的有一篇博客筆記;
以上內容,記以溫之。