首先引入 quartz jar包;
创建java类:
package com.tcwl.vsmp.loanmgt.message;
import com.tcwl.vsmp.external.constant.SmsConstant;
import com.tcwl.vsmp.external.service.sms.SmsProxy;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
/**
* Project Name:
* FileName: SMSScheduler
* Author: 苏凯
* Date: 2018/8/30 15:27
* Description: 定时短信发送
*
* @version 1.0.0
* @since: 1.0.0
* Copyright (C), 2015-2018,
*/
@Configurable
public class SMSScheduler {
/**
* 提醒客户还款
*/
public void sendMessageForClientWithRepayment() {
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " -> Hello, 我是任务 1");
int day = 0;
int days = 0;
// TIMEDPUSHDAY 为配置文件中所配置的天数;查询在这个天数范围内的数据
if (null != TIMEDPUSHDAY) {
day = Integer.parseInt(TIMEDPUSHDAY);
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ");
Date date1 = null;
String format1 = "";
Date date2 = null;
String format2 = "";
for (int i = 0; i < day + 1; i++) {
days = day - 1;
Calendar time1 = Calendar.getInstance();
Calendar time2 = Calendar.getInstance();
days = days - i;
//获取当天的时间范围
// REPAY_DEADLINE 为配置文件中所配置的还款期限;一般为45天
time(days, time1, time2, REPAY_DEADLINE);
date1 = time1.getTime();
format1 = df.format(date1);
date2 = time2.getTime();
format2 = df.format(date2);
if (i < day) {
String message = "距离还款日期天数:" + (day - i) + "日,";
List<LoanTable> loanTables =
service.queryRefundTimeBorrowerInfo(format1, format2
, LoanConstant.LOAN_STATUS_HAS_APPROVE
, LoanConstant.LOAN_STATUS_WILL_EXPIRE
, LoanConstant.LOAN_STATUS_OVER_DUE);
//给即将到期的客户发送短信
sendMessageOverdue(message, loanTables);
} else if (i == day) {
List<LoanTable> loanTables =
service.queryRefundTimeBorrowerInfo2(format1
, LoanConstant.LOAN_STATUS_HAS_APPROVE
, LoanConstant.LOAN_STATUS_WILL_EXPIRE
, LoanConstant.LOAN_STATUS_OVER_DUE);
String message = "已逾期;";
//给逾期客户发短信
sendMessageOverdue(message, loanTables);
}
}
}
}
/**
* @param message
* @param loanTables 提醒客户还款
* 给即将到期的客户发送短信、给逾期客户发短信
*/
private void sendMessageOverdue(String message, List<LoanTable> loanTables) {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Calendar now = Calendar.getInstance();
Date date1 = null;
//逾期时间
String borrowSuccessTime = "";
if (null != loanTables && 0 < loanTables.size()) {
for (int j = 0; j < loanTables.size(); j++) {
//客户手机号
String tel = loanTables.get(j).getBorrower_tel() != null ?
loanTables.get(j).getBorrower_tel() : "";
//客户名
String name = loanTables.get(j).getBorrower_name() != null ?
loanTables.get(j).getBorrower_name() : "";
//还款日期
String refund_time = loanTables.get(j).getRefund_time() != null ?
loanTables.get(j).getRefund_time() : "";
//还款金额
Double amount = loanTables.get(j).getAmount() != null ?
loanTables.get(j).getAmount() : 0.0;
//借款时间
String borrow_success_time = loanTables.get(j).getBorrow_success_time()
!= null ?
loanTables.get(j).getBorrow_success_time() :
"";
//计算逾期时间
borrowSuccessTime = getoverdueTime(df, now, borrow_success_time);
/* System.out.println((tel + "," + name + "先生/女士,您好!"
+ "您的借款金额期到期时间:" + borrowSuccessTime + ", 还款金额:" +
amount
+ "元," + message + "欢迎您使用XXX,祝您体验愉快!【XXX】"));*/
try {
//打开注释,恢复短信功能;
/*SmsProxy.sendSms(tel, name + "先生/女士,您好!"
+ "您的借款金额期到期时间:" +refund_time+", 还款金额:"
+ amount
+ "元,"+message+"欢迎您使用XXXX,祝您体验愉快!
【XXX】", 1,
SmsConstant.SMS_CHANNEL_JIANZHOU_NO_EXAMINE);*/
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/**
* 获取当天的时间范围
*
* @param days
* @param time1
* @param time2 定时推送还款信息包括截止还款日期,距离还款日期天数,
* 到期还款金额,逾期提醒根据借口数据短信或推送通知客户
*/
private void time(int days, Calendar time1, Calendar time2, Integer REPAY_DEADLINE) {
time1.add(Calendar.DATE, (-REPAY_DEADLINE + days));
// 时
time1.set(Calendar.HOUR_OF_DAY, 0);
// 分
time1.set(Calendar.MINUTE, 0);
// 秒
time1.set(Calendar.SECOND, 0);
// 毫秒
time1.set(Calendar.MILLISECOND, 0);
time2.add(Calendar.DATE, (-REPAY_DEADLINE + days));
// 时
time2.set(Calendar.HOUR_OF_DAY, 23);
// 分
time2.set(Calendar.MINUTE, 59);
// 秒
time2.set(Calendar.SECOND, 59);
// 毫秒
time2.set(Calendar.MILLISECOND, 0);
}
/**
* @param now 当前时间
* @param borrow_success_time 借款通过时间
* @return 还款截止时间
* 计算逾期时间
* SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
* Calendar now = Calendar.getInstance();
*/
private String getoverdueTime(SimpleDateFormat df, Calendar now, String borrow_success_time) {
String borrowSuccessTime = "";
Date date1;//计算逾期时间
if (null != borrow_success_time && 0 < borrow_success_time.length()) {
// 表达式对象
Pattern p = Pattern.compile("^[1-9]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])" +
"\\s+(20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d$");
// 创建 Matcher 对象
Matcher m = p.matcher(borrow_success_time);
// 是否完全匹配
if (m.matches()) {
try {
Date parse = df.parse(borrow_success_time);
now.setTime(parse);
//加上到期天数
now.add(Calendar.DATE, REPAY_DEADLINE);
date1 = now.getTime();
borrowSuccessTime = df.format(date1);
} catch (Exception e) {
e.printStackTrace();
}
}
}
return borrowSuccessTime;
}
}
配置定时器 spring-quartz.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 调度器 触发器-->
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<!-- <ref bean="myTrigger"/>
<ref bean="loanExpireSmsTrigger"/>
<ref bean="expandSearchTrigger"/>
<ref bean="zshChargeApplyRecordTrigger"/>
<ref bean="LoanSmsRemindQuartzTrigger"/>
<ref bean="ZshWalletQuartzTrigger"/>
<ref bean="ZshGetFileQuartzTrigger"/>
<ref bean="downloadConsumeFileTrigger"/> 可以配多个任务 -->
<ref bean="cronTrigger_1" />
<ref bean="cronTrigger_2" />
</list>
</property>
</bean>
<!-- 定时任务配置 1-->
<bean name="SMSScheduler" class="com.tcwl.vsmp.loanmgt.message.SMSScheduler"/>
<bean id="SMSSDetail_1" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject">
<ref bean="SMSScheduler" />
</property>
<property name="targetMethod">
<value>sendMessage</value>
</property>
</bean>
<bean id="cronTrigger_1" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail">
<ref bean="SMSSDetail_1" />
</property>
<!-- 每一秒钟执行一次 -->
<property name="cronExpression">
<value>0/1 * * * * ?</value>
</property>
</bean>
<!-- 定时任务配置 2-->
<!--短信通知金鑫逾期的客户名单与已经逾期的客户名单-->
<bean id="SMSSDetail_2" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject">
<ref bean="SMSScheduler" />
</property>
<property name="targetMethod">
<value>sendMessageJinXinWithRepayment</value>
</property>
</bean>
<bean id="cronTrigger_2" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail">
<ref bean="SMSSDetail_2" />
</property>
<!-- 定N 时间执行一次 -->
<property name="cronExpression">
<!-- 读配置文件中的时间 -->
<value>#{prop.SMSSCHEDUlER_JINXING_TIME}</value>
</property>
</bean>
web.xml加载定时配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/classes/spring-quartz.xml
</param-value>
</context-param>
配置文件:
conf/SMSScheduler.properties
#---------------------客户-----------------------------
#定时推送还款信息;截止还款日期前第N天开始推送信息;
TIMEDPUSHDAY = 3
#定时推送还款信息;发送客户时间设定;
SMSSCHEDUlERTIME = 0/20 * * * * ?
#---------------------金鑫-----------------------------
#定时推送还款信息;推送资方手机号配置;
SMSSCHEDUlER_JINXING_IPHONENUM = 18********
#定时推送还款信息;发送时间设定;
SMSSCHEDUlER_JINXING_TIME = 0/20 * * * * ?
#---------------------财务-----------------------------
#还款短信通知财务;手机号
SMSSCHEDUlER_CANWUBU_IPHONENUM = 18********
加载 conf/SMSScheduler.properties 配置文件:
applicationContext.xml
<bean id="prop" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<array>
<value>classpath:conf/*</value>
</array>
</property>
<property name="fileEncoding" value="UTF-8"/>
</bean>
时间计算:cron
可以去这个网站 http://cron.qqe2.com/
下面这张图选择的是每天上午2点发送短信,可参照:
注意:
Spring被用在了越来越多的项目中, quartz也被公认为是比较好用的定时器设置工具, 在这里通过一个demo说明如何使用spring和quartz配置多个定时任务.
环境: eclipse + maven + spring 3.0.6.RELEASE版本 + quartz 1.8.6版本
需要引入的jar包, 这里是采用maven的dependency依赖; 如果没有使用maven, 可以对照着上面的jar包截图一一进行下载. 这里唯一需要注意的就是, 如果使用spring 3.1以下的版本, quartz就需要相应的2.0以下版本, 否则会导致 org.springframework.beans.factory.CannotLoadBeanClassException: Error loading class [org.springframework.scheduling.quartz.CronTriggerBean] for bean with name 'cronTrigger_1' defined in file [E:\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\git-common\WEB-INF\classes\applicationContext.xml]: problem with class file or dependent class; nested exception isjava.lang.IncompatibleClassChangeError: class org.springframework.scheduling.quartz.CronTriggerBean has interface org.quartz.CronTrigger as super class 错误.
后续: 后来使用了spring 4.0.5.RELEASE版本+quartz 2.2.1版本, 还是报出了以上错误, 将quartz降低为1.8.6版本后, 问题消失...