zoukankan      html  css  js  c++  java
  • Web应用定时任务实现

    一、需求:

    项目上有时需要执行一些定时任务,比如:超过2天未处理的问题,邮件自动通知客服、对接人;3天未处理的问题,邮件自动通知客服、对接人和项目经理,同时标为‘紧急’状态;5天未处理的问题,邮件自动通知客服、对接人和项目经理,同时标为‘非常紧急’状态;

    这类定时任务可以用简单的JAVA实现。

    二、SQL准备:

    1. 首先肯定是要先查询出超时的记录,这里需要用到MYSQL的一个数据库自带的函数TIMESTAMPDIFF,计算时间差非常方便:

    语法:

    TIMESTAMPDIFF(interval,datetime_expr1,datetime_expr2)

    返回日期或日期时间表达式datetime_expr1 和datetime_expr2the 之间的整数差。其结果的单位由interval 参数给出。该参数必须是以下值的其中一个:

    FRAC_SECOND。表示间隔是毫秒

    SECOND。秒

    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

    三、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);

    四、在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 }

    上面代码中发送邮件有用到另外的一个类,群发邮件可以参考前面的有一篇博客笔记;

    以上内容,记以温之。

     

    边系鞋带边思考人生.
  • 相关阅读:
    HyperLogLog
    Bitmaps
    正向代理与反向代理的概念
    性能优化——应用服务器性能优化
    Memcached的优点
    前端基础之BOM和DOM
    性能优化——Web前端性能优化
    亡命逃窜---三维搜索
    Sum It Up -- 深搜 ---较难
    排序---对二维数组的排序
  • 原文地址:https://www.cnblogs.com/crazytrip/p/4956273.html
Copyright © 2011-2022 走看看