一、问题描述
最近在开发支付,有三个需求如下:
1.当用户选择某个医生的时间,进行预约,然后下单,下单之后成功支付,在预约时间的前5分钟,实现短信,通知。
2.当用户下单之后半个小时,没有支付,把订单状态改为取消。
3.当用户下单之后,成功支付,一个小时之后有医生对他咨询,把状态改为过期。
二、解决方法
像上面的三种情况肯定得使用定时器,来进行处理,使用的定时器是Spring自带的Spring-Task具体思路如下:
至于相关的cron表达式可通过在线工具,生成:http://cron.qqe2.com/
第一个问题的思路是,设置定时器按每小时的第55分钟执行,然后取当前时间+5分钟和数据库中的时间进行对比,如果相等那就发送短信:
对应的cron表达式为:
0 55 0/1 * * ?
JAVA时间操作:
SimpleDateFormat df =new SimpleDateFormat("yyyy-MM-dd HH:mm");
Calendar nowTime = Calendar.getInstance();
nowTime.add(Calendar.MINUTE, 5);
String currentTime = df.format(nowTime.getTime());
第二个问题的思路是,设置定时器按1分钟扫一次,然后取当前时间减去30分钟和数据库中的时间进行对比,,如果相等那就发送短信:
对应的cron表达式为:
0 0/1 0/1 * * ?
JAVA时间操作:
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
Calendar nowTime2 = Calendar.getInstance();
nowTime2.add(Calendar.MINUTE, -30);//30分钟前的时间
String currentTime = df.format(nowTime2.getTime());
第三个问题的思路和上面的差不多,因为我这是按预约结束时间来算的,预约结束时间是每个小时的第50分钟,所以设置定时器按1小时执行一次,然后取当前时间减去10分钟和数据库中的时间进行对比,,如果相等那就发送短信:
对应的cron表达式为:
0 0 0/1 * * ?
JAVA时间操作:
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MINUTE, -10);// 10分钟之前的时间
String defaultEndDate = df.format(calendar.getTime());
使用spring-task实现定时任务有两种方式:注解和xml配置文件。这里使用xml配置文件的方式加以说明。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:task="http://www.springframework.org/schema/task" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd">
<context:component-scan base-package="com.gz.medicine" />
<task:annotation-driven />
<!--5 分钟: 0 55 0/1 * * ? 每小时的55分扫一次-->
<task:scheduled-tasks>
<task:scheduled ref="fiveMinutesOrdeTask" method="SendMessage"
cron="0 55 0/1 * * ?" />
</task:scheduled-tasks>
<!--1 小时: 0 0/1 * * * ? 1分钟扫一次-->
<task:scheduled-tasks>
<task:scheduled ref="aminuteOutDateOrderTask" method="SendMessage"
cron="0 0/1 * * * ?" />
</task:scheduled-tasks>
<!--30 分钟: 0 0/1 * * * ? 1分钟扫一次-->
<task:scheduled-tasks>
<task:scheduled ref="aminuteTimeoutOrderTask" method="SendMessage"
cron="0 0/1 * * * ?" />
</task:scheduled-tasks>
<!--24 小时: 0 0 0/1 * * ? 1小时扫一次-->
<task:scheduled-tasks>
<task:scheduled ref="aminuteOutDateOrderRefundTask" method="SendMessage"
cron="0 0 0/1 * * ? " />
</task:scheduled-tasks>
<task:scheduler id="scheduler" pool-size="1" />
</beans>
说明:ref参数指定的即任务类,method指定的即需要运行的方法,cron及cronExpression表达式。
然后就是对应的任务类:
@Service("aminuteOutDateOrderTask")
public class AminuteOutDateOrderTask {
public static final Logger LOGGER = Logger.getLogger(AminuteOutDateOrderTask.class);
@Autowired
private HealthOrderService healthOrderService;
@Autowired
private HealthConsultationService healthConsultationService;
@Autowired
private SendMessageService sendMessageService;
@Autowired
private PushMessageService pushMessageService;
/**
* 超时没支付 -- 更改状态
*/
public void SendMessage(){
LOGGER.info("aminuteOutDateOrderTask start ....");
try {
//取当前小时减一个小时
Calendar calendar = Calendar.getInstance();
//calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - 1);
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
LOGGER.info("订单已过期(1小时)--------当前时间: " + df.format(new Date()) + " ----一个小时前的时间:" + df.format(calendar.getTime()));
//前一个小时
String frontTime = df.format(calendar.getTime());
//然后根据时间去数据库匹配
List<HealthyOrder> healthyOrderList = healthOrderService.OutDateOrderList(frontTime);
if(healthyOrderList.size() > 0){
for (HealthyOrder healthorder : healthyOrderList) {
HealthyOrder healthyOrder = new HealthyOrder();
BeanUtils.copyProperties(healthorder,healthyOrder);
//更改订单的状态为8,并记录日志
healthyOrder.setOrderstate("8");
healthOrderService.UpdateOrderAndLog(healthyOrder,"订单已过期,状态更改");
}
}
}catch (Exception e){
LOGGER.error("订单已过期扫描错误: " + e.getMessage() + e);
}
LOGGER.info("aminuteOutDateOrderTask end ....");
}
}