定时任务常常是数据统计必不可少的任务处理方法,这里介绍的是quartz定时任务插件的配置和使用案例,使用场景是定时给余额不足的用户发送短信通知;关于短信通知的设计和实现如下:
1.在applicationContext.xml配置加载定时任务触发器的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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<!-- 资源文件 -->
<!-- 引入配置 -->
<bean class="com./.prop.EncryptProperty">
<property name="locations">
<list>
<value>classpath:config/cloud.properties</value>
</list>
</property>
</bean>
<bean id="appContext" lazy-init="false" class="com./.spring.AppContext"/>
<!-- 导入其他模块的配置 -->
<import resource="classpath:spring/*.xml"/>
<bean class="com./.cms.util.SysCodeUtil"></bean>
<bean class="com./.cms.util.SysThirdUserUtil"></bean>
<bean class="com./.cms.util.ConfigParamUtil"></bean>
</beans>
2.在 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:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task.xsd">
<!-- 定时任务扫描路径 -->
<context:component-scan base-package="com./.cms.quartz"/>
<task:executor id="executor" pool-size="5"/>
<task:scheduler id="scheduler" pool-size="10"/>
<task:annotation-driven executor="executor"
scheduler="scheduler"/>
</beans>
3.对应的com./.cms.quartz包下的任务实例如下:
package com./.cms.quartz;
import com./.cms.bo.DriverAccountBO;
import com./.cms.dao.DriverAccountDao;
import com./.cms.service.DriverAccountIsEnoughService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
/**
* @author
* @Description:账户余额是否足额(不小于0)状态更新定时任务
* @date 2018年10月17日 15:27
*/
@Component
@Transactional
public class DriverAccountIsEnoughTask {
private final Logger log = LoggerFactory
.getLogger(DriverAccountIsEnoughTask.class);
/** CPU核心数 */
private int cpuCoreNum = 4;
@Autowired
private DriverAccountDao dao;
@Resource
private DriverAccountIsEnoughService service;
/**
* @Description: 定义定时任务每天0点2分执行一次,查询要更新状态的账户
* @author
* @date 2018年10月17日 17:16:01
*
*/
//@Scheduled(cron = "0 0/2 * * * ?")
@Scheduled(cron = "0 2 0 ? * *")
public void updateDriverAmountStatus() {
log.info("DriverAccountIsEnoughTask updateDriverAmountStatus begin...");
try {
// 查询待更新的记录并发短信
List<DriverAccountBO> accountList = dao.selectUpdateList();
if (!accountList.isEmpty()) {
service.sendMethods(accountList);
// 短信通知成功,更新正常->欠费的状态
dao.updateAmountStatus1();
}
// 更新欠费->正常的状态
dao.updateAmountStatus0();
} catch (Exception e) {
log.error("账户余额状态定时任务更新异常", e);
}
log.info("DriverAccountIsEnoughTask updateDriverAmountStatus end...");
}
}
4.service处理短信逻辑为:如果amount<=0且amount_status=0的记录发送短信,否则amount>0且amount_status=1的记录更新状态,其中 `amount_status` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '账户余额状态: 0 正常(账户余额不小于0) 1欠费',`amount` int(11) NOT NULL COMMENT '账户余额:单位分';处理代码如下:
/**
* @author
* @Description:账户余额是否充足实时更新方法
* @date 2018年10月18日 10:53
*/
@Service
public class DriverAccountIsEnoughServiceImpl implements
DriverAccountIsEnoughService {
protected static final Logger log = Logger
.getLogger(DriverAccountIsEnoughServiceImpl.class);
// 账户余额状态: 0 正常(账户余额不小于0) 1欠费
private final static byte amount_status_0 = (byte) 0;
private final static byte amount_status_1 = (byte) 1;
/**
* @Description: 批量处理所有的账户记录
* @author
* @date
* @param accountList
* @return
*
*/
@Override
public void sendMethods(List<DriverAccountBO> accountList) {
// 判断记录条件发送短信
for (DriverAccountBO da : accountList) {
// 发送短信条件为:amount<=0且amount_status=0的记录(此判断可去掉,在查询的时候已处理),且不为免发送短信的手机号
Boolean isSend = ((da.getAmount() <= 0 && da.getAmountStatus()
.equals(amount_status_0)))
&& null != da.getMobilePhone()
&& !da.getMobilePhone().equals(
SysCodeUtil.getString("ignoreMobilePhone"));
if (isSend) {
// 发放短信方法
this.sendSubmial(da.getMobilePhone());
}
}
}
}
其中,发送短信的记录查出来,即dao层selectUpdateList方法其查询语句如下:
<!--查询所有待短信通知的账户记录-->
<select id="selectUpdateList" resultType="com./.cms.bo.DriverAccountBO">
<![CDATA[
SELECT DISTINCT
a.account_id, a.driver_id, a.user_id, a.amount, a.create_time, a.amount_status,
b.mobile_phone
FROM driver_account a
LEFT JOIN sys_user b ON b.user_id=a.user_id
WHERE amount <= 0 AND amount_status = 0
]]>
</select>
短信通知成功,更新正常->欠费的状态updateAmountStatus1方法sql为:
<!--更新用户账户记录为1的状态-->
<update id="updateAmountStatus1">
<![CDATA[
update driver_account
set amount_status = 1
where amount <= 0 AND amount_status = 0
]]>
</update>
更新欠费->正常状态的updateAmountStatus0方法sql为:
<!--更新用户账户记录为0的状态-->
<update id="updateAmountStatus0">
<![CDATA[
update driver_account
set amount_status = 0
where amount > 0 AND amount_status = 1
]]>
</update>
至此,定时任务发送短信的功能编码逻辑结束...哈哈哈,是不是很简单?