支付管理端添加定时作业

This commit is contained in:
airven 2023-02-24 18:26:41 +08:00
parent c078ae9293
commit 4d0220f62f
15 changed files with 596 additions and 1 deletions

View File

@ -0,0 +1,68 @@
package com.jeequan.jeepay.core.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("t_sys_job")
public class SysJob implements Serializable {
private static final long serialVersionUID = 1L;
public static final byte NORMAL = 1; //Job状态正常
public static final byte PAUSE = 0; //Job状态暂停
public static final LambdaQueryWrapper<SysJob> gw(){
return new LambdaQueryWrapper<>();
}
/**
* 任务ID
*/
@TableId(value = "job_id", type = IdType.AUTO)
private Integer jobId;
/**
* bean名称
*/
private String beanName;
/**
* 方法名称
*/
private String methodName;
/**
* 方法参数
*/
private String methodParams;
/**
* cron表达式
*/
private String cronExpression;
/**
* 状态1正常 0暂停
*/
private Byte jobStatus;
/**
* 备注
*/
private String remark;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}

View File

@ -0,0 +1,44 @@
package com.jeequan.jeepay.mgr.bootstrap;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.jeequan.jeepay.core.entity.MchNotifyRecord;
import com.jeequan.jeepay.core.entity.SysJob;
import com.jeequan.jeepay.mgr.task.CronTaskRegistrar;
import com.jeequan.jeepay.mgr.task.SchedulingRunnable;
import com.jeequan.jeepay.service.impl.SysJobService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class TaskRunner implements CommandLineRunner {
private static final Logger logger = LoggerFactory.getLogger(TaskRunner.class);
@Autowired
private SysJobService sysJobService;
@Autowired
private CronTaskRegistrar cronTaskRegistrar;
@Override
public void run(String... args) throws Exception {
// 初始加载数据库里状态为正常的定时任务
LambdaQueryWrapper<SysJob> wrapper = SysJob.gw();
List<SysJob> jobList = sysJobService.list(wrapper.eq(SysJob::getJobStatus, SysJob.NORMAL));
if (CollectionUtils.isNotEmpty(jobList)) {
for (SysJob job : jobList) {
SchedulingRunnable task = new SchedulingRunnable(job.getBeanName(), job.getMethodName(), job.getMethodParams());
cronTaskRegistrar.addCronTask(task, job.getCronExpression());
}
logger.info("定时任务已加载完毕...");
}
}
}

View File

@ -0,0 +1,21 @@
package com.jeequan.jeepay.mgr.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
@Configuration
public class SchedulingConfig {
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
// 定时任务执行线程池核心线程数
taskScheduler.setPoolSize(4);
taskScheduler.setRemoveOnCancelPolicy(true);
taskScheduler.setThreadNamePrefix("TaskSchedulerThreadPool-");
return taskScheduler;
}
}

View File

@ -0,0 +1,59 @@
package com.jeequan.jeepay.mgr.task;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.config.CronTask;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Component
public class CronTaskRegistrar implements DisposableBean {
private final Map<Runnable, ScheduledTask> scheduledTasks = new ConcurrentHashMap<>(16);
@Autowired
private TaskScheduler taskScheduler;
public TaskScheduler getScheduler() {
return this.taskScheduler;
}
public void addCronTask(Runnable task, String cronExpression) {
addCronTask(new CronTask(task, cronExpression));
}
public void addCronTask(CronTask cronTask) {
if (cronTask != null) {
Runnable task = cronTask.getRunnable();
if (this.scheduledTasks.containsKey(task)) {
removeCronTask(task);
}
this.scheduledTasks.put(task, scheduleCronTask(cronTask));
}
}
public void removeCronTask(Runnable task) {
ScheduledTask scheduledTask = this.scheduledTasks.remove(task);
if (scheduledTask != null)
scheduledTask.cancel();
}
public ScheduledTask scheduleCronTask(CronTask cronTask) {
ScheduledTask scheduledTask = new ScheduledTask();
scheduledTask.future = this.taskScheduler.schedule(cronTask.getRunnable(), cronTask.getTrigger());
return scheduledTask;
}
@Override
public void destroy() {
for (ScheduledTask task : this.scheduledTasks.values()) {
task.cancel();
}
this.scheduledTasks.clear();
}
}

View File

@ -0,0 +1,19 @@
package com.jeequan.jeepay.mgr.task;
import java.util.concurrent.ScheduledFuture;
public final class ScheduledTask {
volatile ScheduledFuture<?> future;
/**
* 取消定时任务
*/
public void cancel() {
ScheduledFuture<?> future = this.future;
if (future != null) {
future.cancel(true);
}
}
}

View File

@ -0,0 +1,86 @@
package com.jeequan.jeepay.mgr.task;
import com.jeequan.jeepay.mgr.util.SpringContextUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Method;
import java.util.Objects;
public class SchedulingRunnable implements Runnable {
private static final Logger logger = LoggerFactory.getLogger(SchedulingRunnable.class);
private String beanName;
private String methodName;
private String params;
public SchedulingRunnable(String beanName, String methodName) {
this(beanName, methodName, null);
}
public SchedulingRunnable(String beanName, String methodName, String params) {
this.beanName = beanName;
this.methodName = methodName;
this.params = params;
}
@Override
public void run() {
logger.info("定时任务开始执行 - bean{},方法:{},参数:{}", beanName, methodName, params);
long startTime = System.currentTimeMillis();
try {
Object target = SpringContextUtils.getBean(beanName);
Method method = null;
if (StringUtils.isNotEmpty(params)) {
method = target.getClass().getDeclaredMethod(methodName, String.class);
} else {
method = target.getClass().getDeclaredMethod(methodName);
}
ReflectionUtils.makeAccessible(method);
if (StringUtils.isNotEmpty(params)) {
method.invoke(target, params);
} else {
method.invoke(target);
}
} catch (Exception ex) {
logger.error(String.format("定时任务执行异常 - bean%s方法%s参数%s ", beanName, methodName, params), ex);
}
long times = System.currentTimeMillis() - startTime;
logger.info("定时任务执行结束 - bean{},方法:{},参数:{},耗时:{} 毫秒", beanName, methodName, params, times);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SchedulingRunnable that = (SchedulingRunnable) o;
if (params == null) {
return beanName.equals(that.beanName) &&
methodName.equals(that.methodName) &&
that.params == null;
}
return beanName.equals(that.beanName) &&
methodName.equals(that.methodName) &&
params.equals(that.params);
}
@Override
public int hashCode() {
if (params == null) {
return Objects.hash(beanName, methodName);
}
return Objects.hash(beanName, methodName, params);
}
}

View File

@ -0,0 +1,26 @@
package com.jeequan.jeepay.mgr.task.job;
import com.jeequan.jeepay.service.impl.OrderStatisticsCompanyService;
import com.jeequan.jeepay.service.impl.OrderStatisticsDeptService;
import com.jeequan.jeepay.service.impl.OrderStatisticsMerchantService;
import com.jeequan.jeepay.service.impl.PayOrderExtendService;
import org.springframework.beans.factory.annotation.Autowired;
public class AnalysisTask {
@Autowired
private PayOrderExtendService payOrderExtendService;
@Autowired
private OrderStatisticsCompanyService orderStatisticsCompanyService;
@Autowired
private OrderStatisticsDeptService orderStatisticsDeptService;
@Autowired
private OrderStatisticsMerchantService orderStatisticsMerchantService;
public void Analyse(){
//企业结算
}
}

View File

@ -0,0 +1,15 @@
package com.jeequan.jeepay.mgr.task.job;
import org.springframework.stereotype.Component;
@Component("taskJobOne")
public class JobOneTask {
public void taskWithParams(String params) {
System.out.println("taskJobOne-执行有参示例任务:" + params);
}
public void taskNoParams() {
System.out.println("taskJobOne-执行无参示例任务");
}
}

View File

@ -0,0 +1,15 @@
package com.jeequan.jeepay.mgr.task.job;
import org.springframework.stereotype.Component;
@Component("taskJobTwo")
public class JobTwoTask {
public void taskWithParams(String params) {
System.out.println("taskJobTwo-执行有参示例任务:" + params);
}
public void taskNoParams() {
System.out.println("taskJobTwo-执行无参示例任务");
}
}

View File

@ -0,0 +1,43 @@
package com.jeequan.jeepay.mgr.util;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class SpringContextUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
SpringContextUtils.applicationContext = applicationContext;
}
public static Object getBean(String name) {
return applicationContext.getBean(name);
}
public static <T> T getBean(Class<T> requiredType) {
return applicationContext.getBean(requiredType);
}
public static <T> T getBean(String name, Class<T> requiredType) {
return applicationContext.getBean(name, requiredType);
}
public static boolean containsBean(String name) {
return applicationContext.containsBean(name);
}
public static boolean isSingleton(String name) {
return applicationContext.isSingleton(name);
}
public static Class<? extends Object> getType(String name) {
return applicationContext.getType(name);
}
}

View File

@ -0,0 +1,145 @@
package com.jeequan.jeepay.mgr.util;
import lombok.SneakyThrows;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
@Component
public class TimeUtil {
private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
/**
* 获取昨天0点0分0秒的时间
*/
@SneakyThrows
public String getBeforeFirstDayDate() throws Exception {
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
System.out.println("当前星期(日期)" + format.format(calendar.getTime()));
calendar.add(Calendar.DAY_OF_WEEK, 0);
calendar.set(Calendar.DAY_OF_WEEK, 1);
calendar.set(Calendar.HOUR_OF_DAY, 00);//将小时至00
calendar.set(Calendar.MINUTE, 00);//将分钟至00
calendar.set(Calendar.SECOND, 00);//将秒至00
String timeString = format.format(calendar.getTime());
return timeString;
}
/**
* 获取昨天天23点59分59秒的时间
*/
@SneakyThrows
public String getBeforeLastDayDate() throws Exception {
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
calendar.set(Calendar.HOUR_OF_DAY, 23);//将小时至23
calendar.set(Calendar.MINUTE, 59);//将分钟至59
calendar.set(Calendar.SECOND, 59); //将秒至59
String timeString = format.format(calendar.getTime());
return timeString;
}
/**
* 获取上一周1号0点0分0秒的时间
*/
@SneakyThrows
public String getBeforeFirstWeekDate() throws Exception {
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
calendar.add(Calendar.WEEK_OF_YEAR, -1);
System.out.println("上周星期(日期)" + format.format(calendar.getTime()));
calendar.add(Calendar.DAY_OF_WEEK, 0);
calendar.set(Calendar.DAY_OF_WEEK, 1);
calendar.set(Calendar.HOUR_OF_DAY, 00);
calendar.set(Calendar.MINUTE, 00); //将分钟至00
calendar.set(Calendar.SECOND, 00);//将秒至00
String timeString = format.format(calendar.getTime());
return timeString;
}
/**
* 获取上一周最后一天23点59分59秒的时间
*/
@SneakyThrows
public String getBeforeLastWeekDate() throws Exception {
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
calendar.add(Calendar.WEEK_OF_YEAR, -1);
System.out.println("上周星期(日期)" + format.format(calendar.getTime()));
calendar.set(Calendar.HOUR_OF_DAY, 23);//将小时至23
calendar.set(Calendar.MINUTE, 59); //将分钟至59
calendar.set(Calendar.SECOND, 59); //将秒至59
String timeString = format.format(calendar.getTime());
return timeString;
}
/**
* 获取上一个月1号0点0分0秒的时间
*/
@SneakyThrows
public String getBeforeFirstMonthDate() throws Exception {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MONTH, -1);
calendar.set(Calendar.DAY_OF_MONTH, 1);
calendar.set(Calendar.HOUR_OF_DAY, 00);//将小时至00
calendar.set(Calendar.MINUTE, 00);//将分钟至00
calendar.set(Calendar.SECOND, 00); //将秒至00
String timeString = format.format(calendar.getTime());
return timeString;
}
/**
* 获取上个月的最后一天23点59分59秒的时间
*/
@SneakyThrows
public String getBeforeLastMonthDate() throws Exception {
Calendar calendar = Calendar.getInstance();
int month = calendar.get(Calendar.MONTH);
calendar.set(Calendar.MONTH, month - 1);
calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
calendar.set(Calendar.HOUR_OF_DAY, 23); //将小时至23
calendar.set(Calendar.MINUTE, 59); //将分钟至59
calendar.set(Calendar.SECOND, 59);//将秒至59
String timeString = format.format(calendar.getTime());
return timeString;
}
/**
* 获取上年1号0点0分0秒的时间
*/
@SneakyThrows
public String getBeforeFirstYearDate() throws Exception {
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
calendar.add(Calendar.YEAR, -1);
calendar.set(Calendar.DAY_OF_YEAR, 1);
calendar.set(Calendar.HOUR_OF_DAY, 00);//将小时至00
calendar.set(Calendar.MINUTE, 00);//将分钟至00
calendar.set(Calendar.SECOND, 00); //将秒至00
String timeString = format.format(calendar.getTime());
return timeString;
}
/**
* 获取上年的最后一天23点59分59秒的时间
*/
@SneakyThrows
public String getBeforeLastYearDate() throws Exception {
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
calendar.add(Calendar.YEAR, -1);
calendar.set(Calendar.DAY_OF_YEAR, calendar.getActualMaximum(Calendar.DAY_OF_YEAR));
calendar.set(Calendar.HOUR_OF_DAY, 23); //将小时至23
calendar.set(Calendar.MINUTE, 59); //将分钟至59
calendar.set(Calendar.SECOND, 59);//将秒至59
String timeString = format.format(calendar.getTime());
return timeString;
}
}

View File

@ -4,7 +4,8 @@ server:
spring:
redis:
database: 2 #1库运营平台 #2库商户系统 #3库支付网关
# profiles:
# active: dev
#系统业务参数
isys:
jwt-secret: ARNXp4MzjOOQqxtv #生成jwt的秘钥。 要求每个系统有单独的秘钥管理机制。

View File

@ -0,0 +1,19 @@
package com.jeequan.jeepay.service.impl;
import com.jeequan.jeepay.core.entity.SysJob;
import com.jeequan.jeepay.service.mapper.SysJobMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author [mybatis plus generator]
* @since 2023-02-24
*/
@Service
public class SysJobService extends ServiceImpl<SysJobMapper, SysJob> {
}

View File

@ -0,0 +1,16 @@
package com.jeequan.jeepay.service.mapper;
import com.jeequan.jeepay.core.entity.SysJob;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author [mybatis plus generator]
* @since 2023-02-24
*/
public interface SysJobMapper extends BaseMapper<SysJob> {
}

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jeequan.jeepay.service.mapper.SysJobMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.jeequan.jeepay.core.entity.SysJob">
<id column="job_id" property="jobId" />
<result column="bean_name" property="beanName" />
<result column="method_name" property="methodName" />
<result column="method_params" property="methodParams" />
<result column="cron_expression" property="cronExpression" />
<result column="remark" property="remark" />
<result column="job_status" property="jobStatus" />
<result column="create_time" property="createTime" />
<result column="update_time" property="updateTime" />
</resultMap>
</mapper>