Web應用定時任務實現

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 }

上面代碼中發送郵件有用到另外的一個類,羣發郵件能夠參考前面的有一篇博客筆記;

 

以上內容,記以溫之。

相關文章
相關標籤/搜索