一、需求:

项目上有时需要执行一些定时任务,比如:超过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()) <

三、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. 定时器实现

 import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.TimerTask; import com.crm.action.param.QuestionFollowDTO;
import com.crm.dao.BaseDao;
import com.crm.util.SendMailThread; public class TimerTaskAction extends TimerTask{ @Override
public void run() {
// TODO Auto-generated method stub
// System.out.println("this is a timer task...");
/*List<QuestionFollowDTO> list = getResult(queryTimerOutQues(33));
updateQuesLevel(list);
sendMailWarn(list,33);*/
//超过2未超过3天
List<QuestionFollowDTO> outTwoDays = getResult(queryTimerOutQues(2));
updateQuesLevel(outTwoDays);
sendMailWarn(outTwoDays,2); //超过3天未过5天
List<QuestionFollowDTO> outThreeDays = getResult(queryTimerOutQues(3));
updateQuesLevel(outThreeDays);
sendMailWarn(outThreeDays,3); //超过5天
List<QuestionFollowDTO> outFiveDays = getResult(queryTimerOutQues(5));
updateQuesLevel(outFiveDays);
sendMailWarn(outFiveDays,5);
} //查询超过day天未处理的问题
public ResultSet queryTimerOutQues(int days){
String sql = " xxx " ;
switch(days){
case 2:
sql += " and TIMESTAMPDIFF(day,q.createtime,now()) > 2 and TIMESTAMPDIFF(day,q.createtime,now()) <3 " ;
break;
case 3:
sql += " and TIMESTAMPDIFF(day,q.createtime,now()) > 3 and TIMESTAMPDIFF(day,q.createtime,now()) <5 " ;
break;
case 5:
sql += " and TIMESTAMPDIFF(day,q.createtime,now()) > 5 " ;
break;
case 33: //调试
sql += " and TIMESTAMPDIFF(day,q.createtime,now()) > 33 " ;
}
sql += " order by c_id desc " ; // System.out.println("查询问题SQL="+sql); ResultSet rs = BaseDao.executeQuerySQL(null, sql, null); return rs ;
} public List<QuestionFollowDTO> getResult(ResultSet rs){
List<QuestionFollowDTO> list = new ArrayList<QuestionFollowDTO>();
try {
while(rs.next()){
QuestionFollowDTO dto = new QuestionFollowDTO();
dto.setQuesId(rs.getInt("c_id"));
dto.setQuesStatus(rs.getInt("c_status"));
dto.setQuesCreatetime(rs.getString("c_createtime"));
dto.setFromUserId(rs.getInt("c_user_id"));
dto.setFromUserName(rs.getString("fromUserName"));
dto.setFromUserMail(rs.getString("fromUserMail")) ;
dto.setNextUserId(rs.getInt("c_next_user")) ;
dto.setNextUserName(rs.getString("nextUserName"));
dto.setNextUserMail(rs.getString("nextUserMail"));
dto.setQuesTitle(rs.getString("c_title")); list.add(dto);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} return list ;
} /*
* list 超期问题数据
* level 紧急程度:递增更新
*/
public void updateQuesLevel(List<QuestionFollowDTO> list){
if(list!=null && list.size()>0){
int length = list.size();
String querIds = "";
for(int i=0;i<length;i++){
querIds += list.get(i).getQuesId() + ",";
} 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(",")) + " ) " ;
System.out.println("更新问题LEVEL:"+sql); //紧急程度递增 BaseDao.executeUpdateSQL(null, sql, null);
}
} /*
* 发送邮件提醒
* list 超时的问题
* days 超时天数
*/
public void sendMailWarn(List<QuestionFollowDTO> list,int days){
if(list!=null && list.size()>0){
for(int i=0;i<list.size();i++){
String mailAdrs = "" ; //邮箱通知
String managerMailAdr = "" ; //邮箱通知项目经理
String fmail = list.get(i).getFromUserMail();
String nmail = list.get(i).getNextUserMail() ;
mailAdrs += ((fmail==null || fmail.trim().equals("") ? "" : fmail+"," ) + (nmail==null || nmail.trim().equals("") ? "" : nmail ) ) ;
if(days>=3){ //超过3天的通知项目经理
String sql = " select c_email from user where c_isvalid=true and c_roleid = 12 " ; // 查询项目经理邮箱,提醒项目经理:
ResultSet rs = BaseDao.executeQuerySQL(null, sql, null);
try {
while(rs.next()){
managerMailAdr += (rs.getString("c_email") + ",");
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// System.out.println("邮件通知地址:"+mailAdrs);
String mailContent = list.get(i).getQuesTitle();
SendMailThread send = new SendMailThread(mailAdrs,"[系统提示:]您有一个问题超过"+days+"天未处理,请及时登录CRM查看处理!","问题标题:"+mailContent);
//send.start();
if(managerMailAdr.length()>0){
// System.out.println("项目经理通知地址:"+managerMailAdr);
new SendMailThread(managerMailAdr,"[系统提示:CRM中有一个问题超过"+days+"天未处理]","问题标题:"+mailContent).start();
}
}
}
}
}

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

以上内容,记以温之。

Web应用定时任务实现的更多相关文章

  1. ASP.NET Core 实现带认证功能的Web代理服务器

    引言 最近在公司开发了一个项目,项目部署架构图如下: 思路 如图中文本所述,公司大数据集群不允许直接访问外网,需要一个网关服务器代理请求,本处服务器A就是边缘代理服务器的作用. 通常技术人员最快捷的思 ...

  2. [转]web.xml中servlet ,filter ,listener ,interceptor的作用与区别

    原文链接:https://blog.csdn.net/netdevgirl/article/details/51483273 一.概念: 1.servlet:servlet是一种运行服务器端的java ...

  3. Web过滤器和监听器

    1.过滤器 1.1什么是过滤器 Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servle ...

  4. servlet/filter/listener/interceptor区别与联系

    转自:http://www.cnblogs.com/doit8791/p/4209442.html servlet.filter.listener是配置到web.xml中(web.xml 的加载顺序是 ...

  5. servlet、filter、listener、interceptor之间的区别和联系

    一.概念 1.servlet:servlet是一种运行服务器端的java应用程序,具有独立于平台和协议的特性,并且可以动态的生成web页面,它工作在客户端请求与服务器响应的中间层. 2.filter: ...

  6. springMVC源码浅析

    因故,需要学习springmvc,现在demo已经跑起来.列文分析springmvc并简单对比struts2. springmvc的核心对象dispatcherServlet.struts2的核心对象 ...

  7. CAT部署安装文档

    多数软件都在/root/project/codebase/3rdpart redhat7用firewalld取代了iptables,遇到问题请添加redhat7关键字搜索,详情请参见Common ad ...

  8. filter listener interceptor的区别

    转自: http://www.cnblogs.com/shangxiaofei/p/5328377.html https://www.cnblogs.com/jinb/p/6915351.html 一 ...

  9. servlet,listener,filter,interceptor的关系

    1.servlet:servlet是一种运行服务器端的java应用程序,具有独立于平台和协议的特性,并且可以动态的生成web页面,它工作在客户端请求与服务器响应的中间层.最早支持 Servlet 技术 ...

随机推荐

  1. Calendar获取星期

    Calendar的使用举个小栗子: //通过当前时间获取本周周一时间 Date date = new Date(); Calendar calendar = new GregorianCalendar ...

  2. 剑指Offer:面试题31——连续子数组的最大和(java实现)

    问题描述 : 输入一个整数数组,数组里面有正数也有负数.数组中一个或连续几个整数组成一个子数组.求所有子数组的和的最大值.要求时间复杂度为O(n) 思路1:常规解法,不知道怎么描述了.. 代码: bo ...

  3. SQLyog-直接导出JSON格式的数据

          前言:以前做过的一个项目,有这样的一个需求使用搜索引擎来查询对应的区域信息,不过区域信息要先导出来,并且数据格式是JSON格式的,在程序中能实现这个需求,不过下面的这种方法更加的简单,通过 ...

  4. click 事件 arguments.callee 每次点击自动* 2

    今天在测试JQUERY(版本3.0,向下兼容3.0)时发现一个很特别的现象,代码如下: $($('button').get(4)).click(function(){ alert($(this).ht ...

  5. JS中Array详细用法

    1.数组的创建 var name= new Array(); //创建一个数组 name[0]="zhangsan";   //给数组赋值 name[1]="lisi&q ...

  6. 利用JAVA生成二维码

    本文章整理于慕课网的学习视频<JAVA生成二维码>,如果想看视频内容请移步慕课网. 维基百科上对于二维码的解释. 二维条码是指在一维条码的基础上扩展出另一维具有可读性的条码,使用黑白矩形图 ...

  7. Ninject之旅之八:Ninject插件模型(附程序下载)

    摘要 在前面的章节中,我们看了在单一的绑定条件下Ninject能够处理依赖类型,就是说,每个服务类型只绑定到单一的实现类型.然而,有些情况下我们需要绑定一个抽象服务类型到多个实现,这叫多个绑定.多个绑 ...

  8. rt—移植笔记1

    将rtt源码往stm32f407移植的时候,源码串口打印引脚设置有误,以下是源码引脚配置. 以下是原理图 可见配置有误.

  9. MySQL 5.7 Command Line Client输入密码后闪退和windows下mysql忘记root密码的解决办法

    MySQL 5.7 Command Line Client输入密码后闪退的问题: 问题分析: 1.查看mysql command line client默认执行的一些参数.方法:开始->所有程序 ...

  10. 读取excel数据,并进行统计输出

    package cn.cnnic.ops; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFou ...