![84afd35f6f06cd9d6f3600093b3c0ecd.png](https://i-blog.csdnimg.cn/blog_migrate/84ce5cc27728443df642864eb95262fc.jpeg)
新的一周,先记录个笔记在开始工作吧。。
26篇笔记写一下定时任务quartz吧
简单的定时任务Timer:
//Timer定时器
//TimerTask:任务
//firstTime:第一次执行的时间
//peroid:间隔多久再执行
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println("银行计息...");
}
}, date, 5000);
// 24小时 1000*60*60*24
cron表达式
在每年的11月11号11点11分11秒:双十一抢购提醒
![e2d2a53f200667cf624e5ef94fa0b016.png](https://i-blog.csdnimg.cn/blog_migrate/6db2bc129b370c52b9ab0481073a7f1d.jpeg)
复杂的定时任务:
可以用cron表达式转化器,转成自己想要的时间
在线Cron表达式生成器cron.qqe2.comQuartz是一个完全由Java编写的开源作业调度框架,为在Java应用程序中进行作业调度提供了简单却强大的机制。Quartz允许开发人员根据时间间隔来调度作业。
Cron表达式由6或7个空格分隔的时间字段组成:秒 分钟 小时 日期 月份 星期 年(可选)
这些星号由左到右按顺序代表 : * * * * * * *
格式: [秒] [分] [小时] [日] [月] [周] [年]
![c880b1f7accb6e3ba993bec7a122fe5c.png](https://i-blog.csdnimg.cn/blog_migrate/7358159a110b003354ebbba5b223d273.jpeg)
例 "0 0 12 ? * WED" 在每星期三下午12:00 执行,
Cron表达式的7个部分从左到右代表的含义如下
Seconds Minutes Hours Day-of-Month Month Day-of-Week Year
其中Year是可选的
个别子表达式可以包含范围, 例如,在前面的例子里("WED")可以替换成 "MON-FRI", "MON, WED, FRI"甚至"MON-WED,SAT".
每一个字段都有一套可以指定有效值,如
Seconds (秒) :可以用数字0-59 表示,
Minutes(分) :可以用数字0-59 表示,
Hours(时) :可以用数字0-23表示,
Day-of-Month(天) :可以用数字1-31 中的任一一个值,但要注意一些特别的月份
Month(月) :可以用0-11 或用字符串 “JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV and DEC” 表示
Day-of-Week(每周):可以用数字1-7表示(1 = 星期日)或用字符口串“SUN, MON, TUE, WED, THU, FRI and SAT”表示
- “*” 字符代表所有可能的值,因此,“ * ”在子表达式(月)里表示每个月的含义,“ * ”在子表达式(天(星期))表示星期的每一天
- “/”:为特别单位,表示每多长时间执行一次,表示为“每”,字符用来指定数值的增量。
x/y表达一个等步长序列,x为起始值,y为增量步长值。如在分钟字段中使用0/15,则表示为0,15,30和45分钟,而5/15在分钟字段中表示5,20,35,50,你也可以使用*/y,它等同于0/y;
“3/20”表示表示每隔20分钟执行一次,“3”表示从第3分钟开始执行。
- “?”:字符仅被用于日day-of-month和星期这两个子表达式,表示不指定值。
当2个子表达式其中之一被指定了值以后,为了避免冲突,需要将另一个子表达式的值设为“?”
- “L”:该字符只在日期和星期字段中使用,代表“Last”的意思,但它在两个字段中意思不同。L在日期字段中,表示这个月份的最后一天,如一月的31号,非闰年二月的28号;如果L用在星期中,则表示星期六,等同于7。但是,如果L出现在星期字段里,而且在前面有一个数值 X,则表示“这个月的最后X天”,例如,6L表示该月的最后星期五;
- “W”:该字符只能出现在日期字段里,是对前导日期的修饰,表示离该日期最近的工作日。例如15W表示离该月15号最近的 工作日,如果该月15号是星期六,则匹配14号星期五;如果15日是星期日,则匹配16号星期 一;如果15号是星期二,那结果就是15号星期二。但必须注 意关联的匹配日期不能够跨月,如你指定1W,如果1号是星期六,结果匹配的是3号星期一,而非上个月最后的那天。W字符串只能指定单一日期,而不能指定日 期范围;
- “LW组合:在日期字段可以组合使用LW,它的意思是当月的最后一个工作日;
- ““#”:该字符只能在星期字段中使用,表示当月某个工作日。如6#3表示当月的第三个星期五(6表示星期五,#3 表示当前的第三个),而4#5表示当月的第五个星期三,假设当月没有第五个星期三,忽略不触发;
![dd3485b3ca93747a361b18f8f50d23fe.png](https://i-blog.csdnimg.cn/blog_migrate/15ce13c95a441519d20a6af3a32d9921.jpeg)
要为customer_loss定义一个客户流失的标准:在客户订单表order表里面查询最近最近六个月都没有订单的客户,就把这个客户的信息(customer)还有最后一次订单信息(order)表组成customer_loss表。
(客户之前已经有过订单,在order表里面有记录,但是最近6个月一直没有订单)
CREATE TABLE `customer_loss` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '编号',
`customer_id` int(11) DEFAULT NULL COMMENT '客户编号',
`customer_name` varchar(20) DEFAULT NULL COMMENT '客户名称',
`last_order_time` date DEFAULT NULL COMMENT '上次下单日期',
`confirm_loss_time` date DEFAULT NULL COMMENT '确认流失日期',
`status` int(11) DEFAULT NULL COMMENT '状态 0 暂缓流失 1 确认流失',
`loss_reason` varchar(1000) DEFAULT NULL COMMENT '流失原因',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `FK_customer_loss` (`customer_id`),
CONSTRAINT `FK_customer_loss` FOREIGN KEY (`customer_id`) REFERENCES `customer` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8
CREATE TABLE `customer_loss_measure` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '编号',
`customer_loss_id` int(11) DEFAULT NULL COMMENT '客户流失表id',
`measure` varchar(500) DEFAULT NULL COMMENT '暂缓措施',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `FK_customer_loss_measure` (`customer_loss_id`),
CONSTRAINT `FK_customer_loss_measure` FOREIGN KEY (`customer_loss_id`) REFERENCES `customer_loss` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
![da42c49f9adfc5d95833be8e7498de40.png](https://i-blog.csdnimg.cn/blog_migrate/7aeac988677cf95fd6cfac9bab56d450.jpeg)
![9208ac1fe044e6f0813266d830a3bff0.png](https://i-blog.csdnimg.cn/blog_migrate/d88bb8692fbc4d7c59aee824eec2b13d.jpeg)
![1b674c28a542e29159eaac9d974bd3f5.png](https://i-blog.csdnimg.cn/blog_migrate/a0179f88df7fc60b211f8940b98739a9.jpeg)
![b6707c9486875ccfae0ed76c834a58a4.png](https://i-blog.csdnimg.cn/blog_migrate/a47314ae563a2d42a937efa0094413c7.jpeg)
![b883e794b77f8e3d8e743baecb753640.png](https://i-blog.csdnimg.cn/blog_migrate/696765b70cd2a532973a872c33e76ea1.jpeg)
在config包下面创建QuartzConfig
package com.wyh.crm.config;
import com.situ.crm.quartz.FindCustomerLossJob;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
/**
* Quartz配置类
*/
@Configuration
public class QuartzConfig {
/**
* 1.创建Job对象
*/
@Bean
public JobDetailFactoryBean jobDetailFactoryBean(){
JobDetailFactoryBean factory = new JobDetailFactoryBean();
//关联我们自己的Job类
factory.setJobClass(FindCustomerLossJob.class);
return factory;
}
/**
* Cron Trigger
*/
@Bean
public CronTriggerFactoryBean cronTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean){
CronTriggerFactoryBean factory = new CronTriggerFactoryBean();
factory.setJobDetail(jobDetailFactoryBean.getObject());
//设置触发时间
factory.setCronExpression("0/2 * * * * ?");
return factory;
}
/**
* 3.创建Scheduler对象
*/
@Bean
public SchedulerFactoryBean schedulerFactoryBean(CronTriggerFactoryBean cronTriggerFactoryBean){
SchedulerFactoryBean factory = new SchedulerFactoryBean();
//关联trigger
factory.setTriggers(cronTriggerFactoryBean.getObject());
return factory;
}
}
order是mysql的关键字了,我用order做为表名,死活插不进去数据,将order表改为customer_order表。
@Service
public class CustomerLossServiceImpl implements ICustomerLossService{
@Autowired
private CustomerMapper customerMapper;
@Autowired
private CustomerOrderMapper customerOrderMapper;
@Autowired
private CustomerLossMapper customerLossMapper;
@Override
public void checkCustomerLoss() {
System.out.println("CustomerLossServiceImpl.checkCustomerLoss()");
//1.查找所有流失的客户
List<Customer> customerList = customerMapper.findCustomerLoss();
for (Customer customer : customerList) {
//2.实例化客户流失对象
CustomerLoss customerLoss = new CustomerLoss();
customerLoss.setCustomerNo(customer.getNum());//客户编号
customerLoss.setCustomerName(customer.getName());//客户名称
customerLoss.setCustomerManager(customer.getManagerName());//客户经理
//查找这个客户最后一次的订单信息
CustomerOrder customerOrder = customerOrderMapper.findLastOrderByCustomerId(customer.getId());
if (customerOrder != null) {
customerLoss.setLastOrderTime(customerOrder.getOrderDate());//客户最后一次订单时间
} else {
customerLoss.setLastOrderTime(null);
}
//3.添加到客户流失表里面
customerLossMapper.insert(customerLoss);
//4.客户表里面把客户状态修改为1:流失状态
customer.setStatus(1);
customerMapper.updateByPrimaryKeySelective(customer);
}
}
}
-- 在customer表中查找已经流失的客户
-- 涉及到customer和customer_order表。select出来的数据都在customer表。
SELECT *
FROM customer AS c
WHERE id NOT IN
(SELECT customer_id
FROM customer_order
WHERE DATE_ADD(order_date, INTERVAL 6 MONTH) > NOW())
<select id="findCustomerLoss" resultMap="BaseResultMap">
SELECT
<include refid="Base_Column_List" />
FROM customer AS c
WHERE id NOT IN
(SELECT customer_id
FROM customer_order
WHERE DATE_ADD(order_date, INTERVAL 6 MONTH) > NOW())
</select>
-- 在customer_order表中根据客户id查找最后一次订单
SELECT *
FROM customer_order
WHERE customer_id=29
ORDER BY order_date DESC LIMIT 0,1;
<select id="findLastOrderByCustomerId" parameterType="int" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from `customer_order`
WHERE customer_id=#{id}
ORDER BY order_date DESC LIMIT 0,1;
</select>