feat: initial iShare project code
This commit is contained in:
18
pigx-visual/pigx-daemon-quartz/Dockerfile
Normal file
18
pigx-visual/pigx-daemon-quartz/Dockerfile
Normal file
@@ -0,0 +1,18 @@
|
||||
FROM pig4cloud/java:8-jre
|
||||
|
||||
MAINTAINER wangiegie@gmail.com
|
||||
|
||||
ENV TZ=Asia/Shanghai
|
||||
ENV JAVA_OPTS="-Xms128m -Xmx256m -Djava.security.egd=file:/dev/./urandom"
|
||||
|
||||
RUN ln -sf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||
|
||||
RUN mkdir -p /pigx-daemon-quartz
|
||||
|
||||
WORKDIR /pigx-daemon-quartz
|
||||
|
||||
EXPOSE 5007
|
||||
|
||||
ADD ./target/pigx-daemon-quartz.jar ./
|
||||
|
||||
CMD sleep 120;java $JAVA_OPTS -jar pigx-daemon-quartz.jar
|
||||
126
pigx-visual/pigx-daemon-quartz/pom.xml
Normal file
126
pigx-visual/pigx-daemon-quartz/pom.xml
Normal file
@@ -0,0 +1,126 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>com.pig4cloud</groupId>
|
||||
<artifactId>pigx-visual</artifactId>
|
||||
<version>5.2.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>pigx-daemon-quartz</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<description>基于quartz后台跑批定时任务模块</description>
|
||||
|
||||
<dependencies>
|
||||
<!--注册中心客户端-->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
</dependency>
|
||||
<!--配置中心客户端-->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
||||
</dependency>
|
||||
<!--日志处理-->
|
||||
<dependency>
|
||||
<groupId>com.pig4cloud</groupId>
|
||||
<artifactId>pigx-common-log</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.pig4cloud</groupId>
|
||||
<artifactId>pigx-common-data</artifactId>
|
||||
</dependency>
|
||||
<!--mybatis-->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<!--数据库-->
|
||||
<dependency>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
</dependency>
|
||||
<!--mssql-->
|
||||
<dependency>
|
||||
<groupId>com.microsoft.sqlserver</groupId>
|
||||
<artifactId>mssql-jdbc</artifactId>
|
||||
</dependency>
|
||||
<!-- ojdbc8 -->
|
||||
<dependency>
|
||||
<groupId>com.oracle.database.jdbc</groupId>
|
||||
<artifactId>ojdbc8</artifactId>
|
||||
</dependency>
|
||||
<!--PG-->
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
</dependency>
|
||||
<!-- druid 连接池 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<!--swagger-->
|
||||
<dependency>
|
||||
<groupId>com.pig4cloud</groupId>
|
||||
<artifactId>pigx-common-swagger</artifactId>
|
||||
</dependency>
|
||||
<!--spring security 、oauth、jwt依赖-->
|
||||
<dependency>
|
||||
<groupId>com.pig4cloud</groupId>
|
||||
<artifactId>pigx-common-security</artifactId>
|
||||
</dependency>
|
||||
<!-- sentinel-->
|
||||
<dependency>
|
||||
<groupId>com.pig4cloud</groupId>
|
||||
<artifactId>pigx-common-sentinel</artifactId>
|
||||
</dependency>
|
||||
<!--灰度支持-->
|
||||
<dependency>
|
||||
<groupId>com.pig4cloud</groupId>
|
||||
<artifactId>pigx-common-gray</artifactId>
|
||||
</dependency>
|
||||
<!--web 模块-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<!--undertow容器-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-undertow</artifactId>
|
||||
</dependency>
|
||||
<!-- quartz 模块 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-quartz</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>io.fabric8</groupId>
|
||||
<artifactId>docker-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>false</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.pig4cloud.pigx.daemon.quartz;
|
||||
|
||||
import com.pig4cloud.pigx.common.feign.annotation.EnablePigxFeignClients;
|
||||
import com.pig4cloud.pigx.common.security.annotation.EnablePigxResourceServer;
|
||||
import com.pig4cloud.pigx.common.swagger.annotation.EnableOpenApi;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
|
||||
/**
|
||||
* @author frwcloud
|
||||
* @date 2019/01/23 定时任务模块
|
||||
*/
|
||||
@EnableOpenApi("job")
|
||||
@EnablePigxFeignClients
|
||||
@EnablePigxResourceServer
|
||||
@EnableDiscoveryClient
|
||||
@SpringBootApplication
|
||||
public class PigxDaemonQuartzApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(PigxDaemonQuartzApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.config;
|
||||
|
||||
import org.quartz.JobKey;
|
||||
import org.quartz.spi.TriggerFiredBundle;
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
import org.springframework.scheduling.quartz.SpringBeanJobFactory;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author 郑健楠
|
||||
*/
|
||||
class AutowireCapableBeanJobFactory extends SpringBeanJobFactory {
|
||||
|
||||
private final AutowireCapableBeanFactory beanFactory;
|
||||
|
||||
AutowireCapableBeanJobFactory(AutowireCapableBeanFactory beanFactory) {
|
||||
Assert.notNull(beanFactory, "Bean factory must not be null");
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
|
||||
Object jobInstance = super.createJobInstance(bundle);
|
||||
this.beanFactory.autowireBean(jobInstance);
|
||||
|
||||
// 此处必须注入 beanName 不然sentinel 报错
|
||||
JobKey jobKey = bundle.getTrigger().getJobKey();
|
||||
String beanName = jobKey + jobKey.getName();
|
||||
this.beanFactory.initializeBean(jobInstance, beanName);
|
||||
return jobInstance;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.config;
|
||||
|
||||
import com.pig4cloud.pigx.daemon.quartz.constants.PigxQuartzEnum;
|
||||
import com.pig4cloud.pigx.daemon.quartz.service.SysJobService;
|
||||
import com.pig4cloud.pigx.daemon.quartz.util.TaskUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.quartz.Scheduler;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author 郑健楠
|
||||
* <p>
|
||||
* 初始化加载定时任务
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
@AllArgsConstructor
|
||||
public class PigxInitQuartzJob {
|
||||
|
||||
private final SysJobService sysJobService;
|
||||
|
||||
private final TaskUtil taskUtil;
|
||||
|
||||
private final Scheduler scheduler;
|
||||
|
||||
@Bean
|
||||
public void customize() {
|
||||
sysJobService.list().forEach(sysjob -> {
|
||||
if (PigxQuartzEnum.JOB_STATUS_RELEASE.getType().equals(sysjob.getJobStatus())) {
|
||||
taskUtil.removeJob(sysjob, scheduler);
|
||||
}
|
||||
else if (PigxQuartzEnum.JOB_STATUS_RUNNING.getType().equals(sysjob.getJobStatus())) {
|
||||
taskUtil.resumeJob(sysjob, scheduler);
|
||||
}
|
||||
else if (PigxQuartzEnum.JOB_STATUS_NOT_RUNNING.getType().equals(sysjob.getJobStatus())) {
|
||||
taskUtil.pauseJob(sysjob, scheduler);
|
||||
}
|
||||
else {
|
||||
taskUtil.removeJob(sysjob, scheduler);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.config;
|
||||
|
||||
import org.quartz.Calendar;
|
||||
import org.quartz.JobDetail;
|
||||
import org.quartz.Scheduler;
|
||||
import org.quartz.Trigger;
|
||||
import org.quartz.ee.servlet.QuartzInitializerListener;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.quartz.QuartzProperties;
|
||||
import org.springframework.boot.autoconfigure.quartz.SchedulerFactoryBeanCustomizer;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* @author 郑健楠
|
||||
*/
|
||||
@EnableAsync
|
||||
@Configuration
|
||||
@ConditionalOnClass({ Scheduler.class, SchedulerFactoryBean.class })
|
||||
@EnableConfigurationProperties({ QuartzProperties.class })
|
||||
public class PigxQuartzConfig {
|
||||
|
||||
private final QuartzProperties properties;
|
||||
|
||||
private final List<SchedulerFactoryBeanCustomizer> customizers;
|
||||
|
||||
private final JobDetail[] jobDetails;
|
||||
|
||||
private final Map<String, Calendar> calendars;
|
||||
|
||||
private final Trigger[] triggers;
|
||||
|
||||
private final ApplicationContext applicationContext;
|
||||
|
||||
public PigxQuartzConfig(QuartzProperties properties,
|
||||
ObjectProvider<List<SchedulerFactoryBeanCustomizer>> customizers, ObjectProvider<JobDetail[]> jobDetails,
|
||||
ObjectProvider<Map<String, Calendar>> calendars, ObjectProvider<Trigger[]> triggers,
|
||||
ApplicationContext applicationContext) {
|
||||
this.properties = properties;
|
||||
this.customizers = customizers.getIfAvailable();
|
||||
this.jobDetails = jobDetails.getIfAvailable();
|
||||
this.calendars = calendars.getIfAvailable();
|
||||
this.triggers = triggers.getIfAvailable();
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public SchedulerFactoryBean quartzScheduler() {
|
||||
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
|
||||
schedulerFactoryBean.setJobFactory(
|
||||
new AutowireCapableBeanJobFactory(this.applicationContext.getAutowireCapableBeanFactory()));
|
||||
if (!this.properties.getProperties().isEmpty()) {
|
||||
schedulerFactoryBean.setQuartzProperties(this.asProperties(this.properties.getProperties()));
|
||||
}
|
||||
|
||||
if (this.jobDetails != null && this.jobDetails.length > 0) {
|
||||
schedulerFactoryBean.setJobDetails(this.jobDetails);
|
||||
}
|
||||
|
||||
if (this.calendars != null && !this.calendars.isEmpty()) {
|
||||
schedulerFactoryBean.setCalendars(this.calendars);
|
||||
}
|
||||
|
||||
if (this.triggers != null && this.triggers.length > 0) {
|
||||
schedulerFactoryBean.setTriggers(this.triggers);
|
||||
}
|
||||
|
||||
this.customize(schedulerFactoryBean);
|
||||
return schedulerFactoryBean;
|
||||
}
|
||||
|
||||
private Properties asProperties(Map<String, String> source) {
|
||||
Properties properties = new Properties();
|
||||
properties.putAll(source);
|
||||
return properties;
|
||||
}
|
||||
|
||||
private void customize(SchedulerFactoryBean schedulerFactoryBean) {
|
||||
if (this.customizers != null) {
|
||||
Iterator var2 = this.customizers.iterator();
|
||||
|
||||
while (var2.hasNext()) {
|
||||
SchedulerFactoryBeanCustomizer customizer = (SchedulerFactoryBeanCustomizer) var2.next();
|
||||
customizer.customize(schedulerFactoryBean);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化监听器
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public QuartzInitializerListener executorListener() {
|
||||
return new QuartzInitializerListener();
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过SchedulerFactoryBean获取Scheduler的实例
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public Scheduler scheduler() {
|
||||
return quartzScheduler().getScheduler();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.config;
|
||||
|
||||
import org.springframework.boot.autoconfigure.quartz.SchedulerFactoryBeanCustomizer;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
|
||||
|
||||
/**
|
||||
* @author 郑健楠
|
||||
*/
|
||||
@Configuration
|
||||
public class PigxQuartzCustomizerConfig implements SchedulerFactoryBeanCustomizer {
|
||||
|
||||
@Override
|
||||
public void customize(SchedulerFactoryBean schedulerFactoryBean) {
|
||||
schedulerFactoryBean.setWaitForJobsToCompleteOnShutdown(true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.config;
|
||||
|
||||
import com.pig4cloud.pigx.daemon.quartz.constants.PigxQuartzEnum;
|
||||
import com.pig4cloud.pigx.daemon.quartz.entity.SysJob;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.quartz.DisallowConcurrentExecution;
|
||||
import org.quartz.Job;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* @author 郑健楠
|
||||
*
|
||||
* <p>
|
||||
* 动态任务工厂
|
||||
*/
|
||||
@Slf4j
|
||||
@DisallowConcurrentExecution
|
||||
public class PigxQuartzFactory implements Job {
|
||||
|
||||
@Autowired
|
||||
private PigxQuartzInvokeFactory pigxQuartzInvokeFactory;
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void execute(JobExecutionContext jobExecutionContext) {
|
||||
SysJob sysJob = (SysJob) jobExecutionContext.getMergedJobDataMap()
|
||||
.get(PigxQuartzEnum.SCHEDULE_JOB_KEY.getType());
|
||||
pigxQuartzInvokeFactory.init(sysJob, jobExecutionContext.getTrigger());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.config;
|
||||
|
||||
import com.pig4cloud.pigx.daemon.quartz.entity.SysJob;
|
||||
import com.pig4cloud.pigx.daemon.quartz.event.SysJobEvent;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.quartz.Trigger;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author 郑健楠
|
||||
*/
|
||||
@Slf4j
|
||||
@Aspect
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class PigxQuartzInvokeFactory {
|
||||
|
||||
private final ApplicationEventPublisher publisher;
|
||||
|
||||
@SneakyThrows
|
||||
void init(SysJob sysJob, Trigger trigger) {
|
||||
publisher.publishEvent(new SysJobEvent(sysJob, trigger));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.constants;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2019-03-14
|
||||
* <p>
|
||||
* 任务类型枚举
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum JobTypeQuartzEnum {
|
||||
|
||||
/**
|
||||
* 反射java类
|
||||
*/
|
||||
JAVA("1", "反射java类"),
|
||||
|
||||
/**
|
||||
* spring bean 的方式
|
||||
*/
|
||||
SPRING_BEAN("2", "spring bean容器实例"),
|
||||
|
||||
/**
|
||||
* rest 调用
|
||||
*/
|
||||
REST("3", "rest调用"),
|
||||
|
||||
/**
|
||||
* jar
|
||||
*/
|
||||
JAR("4", "jar调用");
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private final String type;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private final String description;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.constants;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @author 郑健楠
|
||||
*
|
||||
* <p>
|
||||
* 定时任务枚举
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum PigxQuartzEnum {
|
||||
|
||||
/**
|
||||
* 错失执行策略默认
|
||||
*/
|
||||
MISFIRE_DEFAULT("0", "默认"),
|
||||
|
||||
/**
|
||||
* 错失执行策略-立即执行错失任务
|
||||
*/
|
||||
MISFIRE_IGNORE_MISFIRES("1", "立即执行错失任务"),
|
||||
|
||||
/**
|
||||
* 错失执行策略-触发一次执行周期执行
|
||||
*/
|
||||
MISFIRE_FIRE_AND_PROCEED("2", "触发一次执行周期执行"),
|
||||
|
||||
/**
|
||||
* 错失执行策略-不触发执行周期执行
|
||||
*/
|
||||
MISFIRE_DO_NOTHING("3", "不触发周期执行"),
|
||||
|
||||
/**
|
||||
* 任务详细信息的key
|
||||
*/
|
||||
SCHEDULE_JOB_KEY("scheduleJob", "获取任务详细信息的key"),
|
||||
|
||||
/**
|
||||
* JOB执行状态:0执行成功
|
||||
*/
|
||||
JOB_LOG_STATUS_SUCCESS("0", "执行成功"),
|
||||
/**
|
||||
* JOB执行状态:1执行失败
|
||||
*/
|
||||
JOB_LOG_STATUS_FAIL("1", "执行失败"),
|
||||
|
||||
/**
|
||||
* JOB状态:1已发布
|
||||
*/
|
||||
JOB_STATUS_RELEASE("1", "已发布"),
|
||||
/**
|
||||
* JOB状态:2运行中
|
||||
*/
|
||||
JOB_STATUS_RUNNING("2", "运行中"),
|
||||
/**
|
||||
* JOB状态:3暂停
|
||||
*/
|
||||
JOB_STATUS_NOT_RUNNING("3", "暂停"),
|
||||
/**
|
||||
* JOB状态:4删除
|
||||
*/
|
||||
JOB_STATUS_DEL("4", "删除");
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private final String type;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private final String description;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,310 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.controller;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.pig4cloud.pigx.common.core.util.R;
|
||||
import com.pig4cloud.pigx.common.excel.annotation.ResponseExcel;
|
||||
import com.pig4cloud.pigx.common.log.annotation.SysLog;
|
||||
import com.pig4cloud.pigx.common.security.util.SecurityUtils;
|
||||
import com.pig4cloud.pigx.daemon.quartz.constants.PigxQuartzEnum;
|
||||
import com.pig4cloud.pigx.daemon.quartz.entity.SysJob;
|
||||
import com.pig4cloud.pigx.daemon.quartz.entity.SysJobLog;
|
||||
import com.pig4cloud.pigx.daemon.quartz.service.SysJobLogService;
|
||||
import com.pig4cloud.pigx.daemon.quartz.service.SysJobService;
|
||||
import com.pig4cloud.pigx.daemon.quartz.util.TaskUtil;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.quartz.Scheduler;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author frwcloud
|
||||
* @date 2019-01-27 10:04:42
|
||||
* <p>
|
||||
* 定时任务管理
|
||||
*/
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
@RequestMapping("/sys-job")
|
||||
@Tag(description = "sys-job", name = "定时任务")
|
||||
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
|
||||
public class SysJobController {
|
||||
|
||||
private final SysJobService sysJobService;
|
||||
|
||||
private final SysJobLogService sysJobLogService;
|
||||
|
||||
private final TaskUtil taskUtil;
|
||||
|
||||
private final Scheduler scheduler;
|
||||
|
||||
/**
|
||||
* 定时任务分页查询
|
||||
* @param page 分页对象
|
||||
* @param sysJob 定时任务调度表
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/page")
|
||||
@Operation(description = "分页定时业务查询")
|
||||
public R getSysJobPage(Page page, SysJob sysJob) {
|
||||
LambdaQueryWrapper<SysJob> wrapper = Wrappers.<SysJob>lambdaQuery()
|
||||
.like(StrUtil.isNotBlank(sysJob.getJobName()), SysJob::getJobName, sysJob.getJobName())
|
||||
.like(StrUtil.isNotBlank(sysJob.getJobGroup()), SysJob::getJobGroup, sysJob.getJobGroup())
|
||||
.eq(StrUtil.isNotBlank(sysJob.getJobStatus()), SysJob::getJobStatus, sysJob.getJobGroup())
|
||||
.eq(StrUtil.isNotBlank(sysJob.getJobExecuteStatus()), SysJob::getJobExecuteStatus,
|
||||
sysJob.getJobExecuteStatus());
|
||||
return R.ok(sysJobService.page(page, wrapper));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过id查询定时任务
|
||||
* @param id id
|
||||
* @return R
|
||||
*/
|
||||
@GetMapping("/{id}")
|
||||
@Operation(description = "唯一标识查询定时任务")
|
||||
public R getById(@PathVariable("id") Long id) {
|
||||
return R.ok(sysJobService.getById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增定时任务
|
||||
* @param sysJob 定时任务调度表
|
||||
* @return R
|
||||
*/
|
||||
@SysLog("新增定时任务")
|
||||
@PostMapping
|
||||
@PreAuthorize("@pms.hasPermission('job_sys_job_add')")
|
||||
@Operation(description = "新增定时任务")
|
||||
public R save(@RequestBody SysJob sysJob) {
|
||||
sysJob.setJobStatus(PigxQuartzEnum.JOB_STATUS_RELEASE.getType());
|
||||
sysJob.setCreateBy(SecurityUtils.getUser().getUsername());
|
||||
this.taskUtil.removeJob(sysJob, scheduler);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改定时任务
|
||||
* @param sysJob 定时任务调度表
|
||||
* @return R
|
||||
*/
|
||||
@SysLog("修改定时任务")
|
||||
@PutMapping
|
||||
@PreAuthorize("@pms.hasPermission('job_sys_job_edit')")
|
||||
@Operation(description = "修改定时任务")
|
||||
public R updateById(@RequestBody SysJob sysJob) {
|
||||
sysJob.setUpdateBy(SecurityUtils.getUser().getUsername());
|
||||
SysJob querySysJob = this.sysJobService.getById(sysJob.getJobId());
|
||||
if (PigxQuartzEnum.JOB_STATUS_NOT_RUNNING.getType().equals(querySysJob.getJobStatus())) {
|
||||
this.taskUtil.addOrUpateJob(sysJob, scheduler);
|
||||
sysJobService.updateById(sysJob);
|
||||
}
|
||||
else if (PigxQuartzEnum.JOB_STATUS_RELEASE.getType().equals(querySysJob.getJobStatus())) {
|
||||
sysJobService.updateById(sysJob);
|
||||
}
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过id删除定时任务
|
||||
* @param id id
|
||||
* @return R
|
||||
*/
|
||||
@SysLog("删除定时任务")
|
||||
@DeleteMapping("/{id}")
|
||||
@PreAuthorize("@pms.hasPermission('job_sys_job_del')")
|
||||
@Operation(description = "唯一标识查询定时任务,暂停任务才能删除")
|
||||
public R removeById(@PathVariable Long id) {
|
||||
SysJob querySysJob = this.sysJobService.getById(id);
|
||||
if (PigxQuartzEnum.JOB_STATUS_NOT_RUNNING.getType().equals(querySysJob.getJobStatus())) {
|
||||
this.taskUtil.removeJob(querySysJob, scheduler);
|
||||
this.sysJobService.removeById(id);
|
||||
}
|
||||
else if (PigxQuartzEnum.JOB_STATUS_RELEASE.getType().equals(querySysJob.getJobStatus())) {
|
||||
this.sysJobService.removeById(id);
|
||||
}
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 暂停全部定时任务
|
||||
* @return
|
||||
*/
|
||||
@SysLog("暂停全部定时任务")
|
||||
@PostMapping("/shutdown-jobs")
|
||||
@PreAuthorize("@pms.hasPermission('job_sys_job_shutdown_job')")
|
||||
@Operation(description = "暂停全部定时任务")
|
||||
public R shutdownJobs() {
|
||||
taskUtil.pauseJobs(scheduler);
|
||||
long count = this.sysJobService.count(
|
||||
new LambdaQueryWrapper<SysJob>().eq(SysJob::getJobStatus, PigxQuartzEnum.JOB_STATUS_RUNNING.getType()));
|
||||
if (count <= 0) {
|
||||
return R.ok("无正在运行定时任务");
|
||||
}
|
||||
else {
|
||||
// 更新定时任务状态条件,运行状态2更新为暂停状态2
|
||||
this.sysJobService.update(
|
||||
SysJob.builder().jobStatus(PigxQuartzEnum.JOB_STATUS_NOT_RUNNING.getType()).build(),
|
||||
new UpdateWrapper<SysJob>().lambda().eq(SysJob::getJobStatus,
|
||||
PigxQuartzEnum.JOB_STATUS_RUNNING.getType()));
|
||||
return R.ok("暂停成功");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动全部定时任务
|
||||
* @return
|
||||
*/
|
||||
@SysLog("启动全部定时任务")
|
||||
@PostMapping("/start-jobs")
|
||||
@PreAuthorize("@pms.hasPermission('job_sys_job_start_job')")
|
||||
@Operation(description = "启动全部定时任务")
|
||||
public R startJobs() {
|
||||
// 更新定时任务状态条件,暂停状态3更新为运行状态2
|
||||
this.sysJobService.update(SysJob.builder().jobStatus(PigxQuartzEnum.JOB_STATUS_RUNNING.getType()).build(),
|
||||
new UpdateWrapper<SysJob>().lambda().eq(SysJob::getJobStatus,
|
||||
PigxQuartzEnum.JOB_STATUS_NOT_RUNNING.getType()));
|
||||
taskUtil.startJobs(scheduler);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新全部定时任务
|
||||
* @return
|
||||
*/
|
||||
@SysLog("刷新全部定时任务")
|
||||
@PostMapping("/refresh-jobs")
|
||||
@PreAuthorize("@pms.hasPermission('job_sys_job_refresh_job')")
|
||||
@Operation(description = "刷新全部定时任务")
|
||||
public R refreshJobs() {
|
||||
sysJobService.list().forEach((sysjob) -> {
|
||||
if (PigxQuartzEnum.JOB_STATUS_RELEASE.getType().equals(sysjob.getJobStatus())
|
||||
|| PigxQuartzEnum.JOB_STATUS_DEL.getType().equals(sysjob.getJobStatus())) {
|
||||
taskUtil.removeJob(sysjob, scheduler);
|
||||
}
|
||||
else if (PigxQuartzEnum.JOB_STATUS_RUNNING.getType().equals(sysjob.getJobStatus())
|
||||
|| PigxQuartzEnum.JOB_STATUS_NOT_RUNNING.getType().equals(sysjob.getJobStatus())) {
|
||||
taskUtil.addOrUpateJob(sysjob, scheduler);
|
||||
}
|
||||
else {
|
||||
taskUtil.removeJob(sysjob, scheduler);
|
||||
}
|
||||
});
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动定时任务
|
||||
* @param jobId
|
||||
* @return
|
||||
*/
|
||||
@SysLog("启动定时任务")
|
||||
@PostMapping("/start-job/{id}")
|
||||
@PreAuthorize("@pms.hasPermission('job_sys_job_start_job')")
|
||||
@Operation(description = "启动定时任务")
|
||||
public R startJob(@PathVariable("id") Long jobId) {
|
||||
SysJob querySysJob = this.sysJobService.getById(jobId);
|
||||
if (querySysJob != null && PigxQuartzEnum.JOB_LOG_STATUS_FAIL.getType().equals(querySysJob.getJobStatus())) {
|
||||
taskUtil.addOrUpateJob(querySysJob, scheduler);
|
||||
}
|
||||
else {
|
||||
taskUtil.resumeJob(querySysJob, scheduler);
|
||||
}
|
||||
// 更新定时任务状态条件,暂停状态3更新为运行状态2
|
||||
this.sysJobService.updateById(
|
||||
SysJob.builder().jobId(jobId).jobStatus(PigxQuartzEnum.JOB_STATUS_RUNNING.getType()).build());
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动定时任务
|
||||
* @param jobId
|
||||
* @return
|
||||
*/
|
||||
@SysLog("立刻执行定时任务")
|
||||
@PostMapping("/run-job/{id}")
|
||||
@PreAuthorize("@pms.hasPermission('job_sys_job_run_job')")
|
||||
@Operation(description = "立刻执行定时任务")
|
||||
public R runJob(@PathVariable("id") Long jobId) {
|
||||
SysJob querySysJob = this.sysJobService.getById(jobId);
|
||||
return TaskUtil.runOnce(scheduler, querySysJob) ? R.ok() : R.failed();
|
||||
}
|
||||
|
||||
/**
|
||||
* 暂停定时任务
|
||||
* @return
|
||||
*/
|
||||
@SysLog("暂停定时任务")
|
||||
@PostMapping("/shutdown-job/{id}")
|
||||
@PreAuthorize("@pms.hasPermission('job_sys_job_shutdown_job')")
|
||||
@Operation(description = "暂停定时任务")
|
||||
public R shutdownJob(@PathVariable("id") Long id) {
|
||||
SysJob querySysJob = this.sysJobService.getById(id);
|
||||
// 更新定时任务状态条件,运行状态2更新为暂停状态3
|
||||
this.sysJobService.updateById(SysJob.builder().jobId(querySysJob.getJobId())
|
||||
.jobStatus(PigxQuartzEnum.JOB_STATUS_NOT_RUNNING.getType()).build());
|
||||
taskUtil.pauseJob(querySysJob, scheduler);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 唯一标识查询定时执行日志
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/job-log")
|
||||
@Operation(description = "唯一标识查询定时执行日志")
|
||||
public R getJobLog(Page page, SysJobLog sysJobLog) {
|
||||
return R.ok(sysJobLogService.page(page, Wrappers.query(sysJobLog)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 检验任务名称和任务组联合是否唯一
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/is-valid-task-name")
|
||||
@Operation(description = "检验任务名称和任务组联合是否唯一")
|
||||
public R isValidTaskName(@RequestParam String jobName, @RequestParam String jobGroup) {
|
||||
return this.sysJobService
|
||||
.count(Wrappers.query(SysJob.builder().jobName(jobName).jobGroup(jobGroup).build())) > 0
|
||||
? R.failed("任务重复,请检查此组内是否已包含同名任务") : R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出任务
|
||||
* @param sysJob
|
||||
* @return
|
||||
*/
|
||||
@ResponseExcel
|
||||
@GetMapping("/export")
|
||||
@Operation(description = "导出任务")
|
||||
public List<SysJob> export(SysJob sysJob) {
|
||||
return sysJobService.list(Wrappers.query(sysJob));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.controller;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.pig4cloud.pigx.common.core.util.R;
|
||||
import com.pig4cloud.pigx.daemon.quartz.entity.SysJobLog;
|
||||
import com.pig4cloud.pigx.daemon.quartz.service.SysJobLogService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* @author frwcloud
|
||||
* <p>
|
||||
* 定时任务执行日志表
|
||||
*/
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
@RequestMapping("/sys-job-log")
|
||||
@Tag(description = "sys-job-log", name = "定时任务日志")
|
||||
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
|
||||
public class SysJobLogController {
|
||||
|
||||
private final SysJobLogService sysJobLogService;
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
* @param page 分页对象
|
||||
* @param sysJobLog 定时任务执行日志表
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/page")
|
||||
@Operation(description = "分页定时任务日志查询")
|
||||
public R getSysJobLogPage(Page page, SysJobLog sysJobLog) {
|
||||
return R.ok(sysJobLogService.page(page, Wrappers.query(sysJobLog)));
|
||||
}
|
||||
|
||||
@DeleteMapping
|
||||
@Operation(description = "批量删除日志")
|
||||
public R deleteLogs(@RequestBody Long[] ids) {
|
||||
return R.ok(sysJobLogService.removeBatchByIds(CollUtil.toList(ids)));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.extension.activerecord.Model;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 定时任务调度表
|
||||
*
|
||||
* @author frwcloud
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(description = "定时任务")
|
||||
public class SysJob extends Model<SysJob> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 任务id
|
||||
*/
|
||||
@TableId(value = "job_id", type = IdType.ASSIGN_ID)
|
||||
private Long jobId;
|
||||
|
||||
/**
|
||||
* 任务名称
|
||||
*/
|
||||
private String jobName;
|
||||
|
||||
/**
|
||||
* 任务组名
|
||||
*/
|
||||
private String jobGroup;
|
||||
|
||||
/**
|
||||
* 组内执行顺利,值越大执行优先级越高,最大值9,最小值1
|
||||
*/
|
||||
private String jobOrder;
|
||||
|
||||
/**
|
||||
* 1、java类;2、spring bean名称;3、rest调用;4、jar调用;9其他
|
||||
*/
|
||||
private String jobType;
|
||||
|
||||
/**
|
||||
* job_type=3时,rest调用地址,仅支持rest get协议,需要增加String返回值,0成功,1失败;job_type=4时,jar路径;其它值为空
|
||||
*/
|
||||
private String executePath;
|
||||
|
||||
/**
|
||||
* job_type=1时,类完整路径;job_type=2时,spring bean名称;其它值为空
|
||||
*/
|
||||
private String className;
|
||||
|
||||
/**
|
||||
* 任务方法
|
||||
*/
|
||||
private String methodName;
|
||||
|
||||
/**
|
||||
* 参数值
|
||||
*/
|
||||
private String methodParamsValue;
|
||||
|
||||
/**
|
||||
* cron执行表达式
|
||||
*/
|
||||
private String cronExpression;
|
||||
|
||||
/**
|
||||
* 错失执行策略(1错失周期立即执行 2错失周期执行一次 3下周期执行)
|
||||
*/
|
||||
private String misfirePolicy;
|
||||
|
||||
/**
|
||||
* 1、多租户任务;2、非多租户任务
|
||||
*/
|
||||
private String jobTenantType;
|
||||
|
||||
/**
|
||||
* 状态(0、未发布;1、已发布;2、运行中;3、暂停;4、删除;)
|
||||
*/
|
||||
private String jobStatus;
|
||||
|
||||
/**
|
||||
* 状态(0正常 1异常)
|
||||
*/
|
||||
private String jobExecuteStatus;
|
||||
|
||||
/**
|
||||
* 创建者
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private String createBy;
|
||||
|
||||
/**
|
||||
* 更新者
|
||||
*/
|
||||
@TableField(fill = FieldFill.UPDATE)
|
||||
private String updateBy;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.UPDATE)
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 首次执行时间
|
||||
*/
|
||||
private LocalDateTime startTime;
|
||||
|
||||
/**
|
||||
* 上次执行时间
|
||||
*/
|
||||
private LocalDateTime previousTime;
|
||||
|
||||
/**
|
||||
* 下次执行时间
|
||||
*/
|
||||
private LocalDateTime nextTime;
|
||||
|
||||
/**
|
||||
* 租户id
|
||||
*/
|
||||
private Long tenantId;
|
||||
|
||||
/**
|
||||
* 备注信息
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.extension.activerecord.Model;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 定时任务执行日志表
|
||||
*
|
||||
* @author frwcloud
|
||||
* @date 2019-01-27 13:40:20
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(description = "定时任务日志")
|
||||
public class SysJobLog extends Model<SysJobLog> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 任务日志ID
|
||||
*/
|
||||
@TableId(value = "job_log_id", type = IdType.ASSIGN_ID)
|
||||
private Long jobLogId;
|
||||
|
||||
/**
|
||||
* 任务id
|
||||
*/
|
||||
private Long jobId;
|
||||
|
||||
/**
|
||||
* 任务名称
|
||||
*/
|
||||
private String jobName;
|
||||
|
||||
/**
|
||||
* 任务组名
|
||||
*/
|
||||
private String jobGroup;
|
||||
|
||||
/**
|
||||
* 组内执行顺利,值越大执行优先级越高,最大值9,最小值1
|
||||
*/
|
||||
private String jobOrder;
|
||||
|
||||
/**
|
||||
* 1、java类;2、spring bean名称;3、rest调用;4、jar调用;9其他
|
||||
*/
|
||||
private String jobType;
|
||||
|
||||
/**
|
||||
* job_type=3时,rest调用地址,仅支持post协议;job_type=4时,jar路径;其它值为空
|
||||
*/
|
||||
private String executePath;
|
||||
|
||||
/**
|
||||
* job_type=1时,类完整路径;job_type=2时,spring bean名称;其它值为空
|
||||
*/
|
||||
private String className;
|
||||
|
||||
/**
|
||||
* 任务方法
|
||||
*/
|
||||
private String methodName;
|
||||
|
||||
/**
|
||||
* 参数值
|
||||
*/
|
||||
private String methodParamsValue;
|
||||
|
||||
/**
|
||||
* cron执行表达式
|
||||
*/
|
||||
private String cronExpression;
|
||||
|
||||
/**
|
||||
* 日志信息
|
||||
*/
|
||||
private String jobMessage;
|
||||
|
||||
/**
|
||||
* 执行状态(0正常 1失败)
|
||||
*/
|
||||
private String jobLogStatus;
|
||||
|
||||
/**
|
||||
* 执行时间
|
||||
*/
|
||||
private String executeTime;
|
||||
|
||||
/**
|
||||
* 异常信息
|
||||
*/
|
||||
private String exceptionInfo;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 租户id
|
||||
*/
|
||||
private Long tenantId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.event;
|
||||
|
||||
import com.pig4cloud.pigx.daemon.quartz.entity.SysJob;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.quartz.Trigger;
|
||||
|
||||
/**
|
||||
* @author frwcloud 定时任务多线程事件
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class SysJobEvent {
|
||||
|
||||
private final SysJob sysJob;
|
||||
|
||||
private final Trigger trigger;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.event;
|
||||
|
||||
import com.pig4cloud.pigx.daemon.quartz.entity.SysJob;
|
||||
import com.pig4cloud.pigx.daemon.quartz.util.TaskInvokUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.quartz.Trigger;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author frwcloud 异步监听定时任务事件
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SysJobListener {
|
||||
|
||||
private final TaskInvokUtil taskInvokUtil;
|
||||
|
||||
@Async
|
||||
@Order
|
||||
@EventListener(SysJobEvent.class)
|
||||
public void comSysJob(SysJobEvent event) {
|
||||
SysJob sysJob = event.getSysJob();
|
||||
Trigger trigger = event.getTrigger();
|
||||
taskInvokUtil.invokMethod(sysJob, trigger);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.event;
|
||||
|
||||
import com.pig4cloud.pigx.daemon.quartz.entity.SysJobLog;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @author frwcloud 定时任务日志多线程事件
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class SysJobLogEvent {
|
||||
|
||||
private final SysJobLog sysJobLog;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.event;
|
||||
|
||||
import com.pig4cloud.pigx.daemon.quartz.entity.SysJobLog;
|
||||
import com.pig4cloud.pigx.daemon.quartz.service.SysJobLogService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author frwcloud 异步监听定时任务日志事件
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SysJobLogListener {
|
||||
|
||||
private final SysJobLogService sysJobLogService;
|
||||
|
||||
@Async
|
||||
@Order
|
||||
@EventListener(SysJobLogEvent.class)
|
||||
public void saveSysJobLog(SysJobLogEvent event) {
|
||||
SysJobLog sysJobLog = event.getSysJobLog();
|
||||
sysJobLogService.save(sysJobLog);
|
||||
log.info("执行定时任务日志");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.exception;
|
||||
|
||||
/**
|
||||
* 定时任务异常
|
||||
*
|
||||
* @author 郑健楠
|
||||
*/
|
||||
public class TaskException extends Exception {
|
||||
|
||||
public TaskException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public TaskException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.mapper;
|
||||
|
||||
import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
|
||||
import com.pig4cloud.pigx.daemon.quartz.entity.SysJobLog;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 定时任务执行日志表
|
||||
*
|
||||
* @author frwcloud
|
||||
* @date 2019-01-27 13:40:20
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysJobLogMapper extends PigxBaseMapper<SysJobLog> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.mapper;
|
||||
|
||||
import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
|
||||
import com.pig4cloud.pigx.daemon.quartz.entity.SysJob;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 定时任务调度表
|
||||
*
|
||||
* @author frwcloud
|
||||
* @date 2019-01-27 10:04:42
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysJobMapper extends PigxBaseMapper<SysJob> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.pig4cloud.pigx.daemon.quartz.entity.SysJobLog;
|
||||
|
||||
/**
|
||||
* 定时任务执行日志表
|
||||
*
|
||||
* @author frwcloud
|
||||
* @date 2019-01-27 13:40:20
|
||||
*/
|
||||
public interface SysJobLogService extends IService<SysJobLog> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.pig4cloud.pigx.daemon.quartz.entity.SysJob;
|
||||
|
||||
/**
|
||||
* 定时任务调度表
|
||||
*
|
||||
* @author frwcloud
|
||||
* @date 2019-01-27 10:04:42
|
||||
*/
|
||||
public interface SysJobService extends IService<SysJob> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.pig4cloud.pigx.daemon.quartz.entity.SysJobLog;
|
||||
import com.pig4cloud.pigx.daemon.quartz.mapper.SysJobLogMapper;
|
||||
import com.pig4cloud.pigx.daemon.quartz.service.SysJobLogService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 定时任务执行日志表
|
||||
*
|
||||
* @author frwcloud
|
||||
* @date 2019-01-27 13:40:20
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class SysJobLogServiceImpl extends ServiceImpl<SysJobLogMapper, SysJobLog> implements SysJobLogService {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.pig4cloud.pigx.daemon.quartz.entity.SysJob;
|
||||
import com.pig4cloud.pigx.daemon.quartz.mapper.SysJobMapper;
|
||||
import com.pig4cloud.pigx.daemon.quartz.service.SysJobService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 定时任务调度表
|
||||
*
|
||||
* @author frwcloud
|
||||
* @date 2019-01-27 10:04:42
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class SysJobServiceImpl extends ServiceImpl<SysJobMapper, SysJob> implements SysJobService {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.pig4cloud.pigx.daemon.quartz.task;
|
||||
|
||||
import com.pig4cloud.pigx.common.core.util.R;
|
||||
import com.pig4cloud.pigx.common.security.annotation.Inner;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 用于测试REST风格调用的demo
|
||||
*
|
||||
* @author lishangbu
|
||||
* @date 2019/3/25
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/inner-job")
|
||||
public class RestTaskDemo {
|
||||
|
||||
/**
|
||||
* 测试REST风格调用定时任务的演示方法
|
||||
*/
|
||||
@Inner(value = false)
|
||||
@GetMapping("/{param}")
|
||||
public R demoMethod(@PathVariable("param") String param) {
|
||||
log.info("测试于:{},传入参数{}", LocalDateTime.now(), param);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.task;
|
||||
|
||||
import com.pig4cloud.pigx.daemon.quartz.constants.PigxQuartzEnum;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* @author 郑健楠
|
||||
*/
|
||||
@Slf4j
|
||||
@Component("demo")
|
||||
public class SpringBeanTaskDemo {
|
||||
|
||||
/**
|
||||
* 测试Spring Bean的演示方法
|
||||
*/
|
||||
@SneakyThrows
|
||||
public String demoMethod(String para) {
|
||||
log.info("测试于:{},输入参数{}", LocalDateTime.now(), para);
|
||||
return PigxQuartzEnum.JOB_LOG_STATUS_SUCCESS.getType();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.util;
|
||||
|
||||
import com.pig4cloud.pigx.daemon.quartz.entity.SysJob;
|
||||
import com.pig4cloud.pigx.daemon.quartz.exception.TaskException;
|
||||
|
||||
/**
|
||||
* 定时任务反射实现接口类
|
||||
*
|
||||
* @author 郑健楠
|
||||
*/
|
||||
public interface ITaskInvok {
|
||||
|
||||
/**
|
||||
* 执行反射方法
|
||||
* @param sysJob 配置类
|
||||
* @throws TaskException
|
||||
*/
|
||||
void invokMethod(SysJob sysJob) throws TaskException;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.util;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.pig4cloud.pigx.daemon.quartz.entity.SysJob;
|
||||
import com.pig4cloud.pigx.daemon.quartz.exception.TaskException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 定时任务可执行jar反射实现
|
||||
*
|
||||
* @author 郑健楠
|
||||
*/
|
||||
@Slf4j
|
||||
@Component("jarTaskInvok")
|
||||
public class JarTaskInvok implements ITaskInvok {
|
||||
|
||||
@Override
|
||||
public void invokMethod(SysJob sysJob) throws TaskException {
|
||||
ProcessBuilder processBuilder = new ProcessBuilder();
|
||||
File jar = new File(sysJob.getExecutePath());
|
||||
processBuilder.directory(jar.getParentFile());
|
||||
List<String> commands = new ArrayList<>();
|
||||
commands.add("java");
|
||||
commands.add("-jar");
|
||||
commands.add(sysJob.getExecutePath());
|
||||
if (StrUtil.isNotEmpty(sysJob.getMethodParamsValue())) {
|
||||
commands.add(sysJob.getMethodParamsValue());
|
||||
}
|
||||
processBuilder.command(commands);
|
||||
try {
|
||||
processBuilder.start();
|
||||
}
|
||||
catch (IOException e) {
|
||||
log.error("定时任务jar反射执行异常,执行任务:{}", sysJob.getExecutePath());
|
||||
throw new TaskException("定时任务jar反射执行异常,执行任务:" + sysJob.getExecutePath());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.util;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.pig4cloud.pigx.daemon.quartz.constants.PigxQuartzEnum;
|
||||
import com.pig4cloud.pigx.daemon.quartz.entity.SysJob;
|
||||
import com.pig4cloud.pigx.daemon.quartz.exception.TaskException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* 定时任务java class反射实现
|
||||
*
|
||||
* @author 郑健楠
|
||||
*/
|
||||
@Component("javaClassTaskInvok")
|
||||
@Slf4j
|
||||
public class JavaClassTaskInvok implements ITaskInvok {
|
||||
|
||||
@Override
|
||||
public void invokMethod(SysJob sysJob) throws TaskException {
|
||||
Object obj;
|
||||
Class clazz;
|
||||
Method method;
|
||||
Object returnValue;
|
||||
try {
|
||||
if (StrUtil.isNotEmpty(sysJob.getMethodParamsValue())) {
|
||||
clazz = Class.forName(sysJob.getClassName());
|
||||
obj = clazz.newInstance();
|
||||
method = clazz.getDeclaredMethod(sysJob.getMethodName(), String.class);
|
||||
returnValue = method.invoke(obj, sysJob.getMethodParamsValue());
|
||||
}
|
||||
else {
|
||||
clazz = Class.forName(sysJob.getClassName());
|
||||
obj = clazz.newInstance();
|
||||
method = clazz.getDeclaredMethod(sysJob.getMethodName());
|
||||
returnValue = method.invoke(obj);
|
||||
}
|
||||
if (StrUtil.isEmpty(returnValue.toString())
|
||||
|| PigxQuartzEnum.JOB_LOG_STATUS_FAIL.getType().equals(returnValue.toString())) {
|
||||
log.error("定时任务javaClassTaskInvok异常,执行任务:{}", sysJob.getClassName());
|
||||
throw new TaskException("定时任务javaClassTaskInvok业务执行失败,任务:" + sysJob.getClassName());
|
||||
}
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
log.error("定时任务java反射类没有找到,执行任务:{}", sysJob.getClassName());
|
||||
throw new TaskException("定时任务java反射类没有找到,执行任务:" + sysJob.getClassName());
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
log.error("定时任务java反射类异常,执行任务:{}", sysJob.getClassName());
|
||||
throw new TaskException("定时任务java反射类异常,执行任务:" + sysJob.getClassName());
|
||||
}
|
||||
catch (InstantiationException e) {
|
||||
log.error("定时任务java反射类异常,执行任务:{}", sysJob.getClassName());
|
||||
throw new TaskException("定时任务java反射类异常,执行任务:" + sysJob.getClassName());
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
log.error("定时任务java反射执行方法名异常,执行任务:{}", sysJob.getClassName());
|
||||
throw new TaskException("定时任务java反射执行方法名异常,执行任务:" + sysJob.getClassName());
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
log.error("定时任务java反射执行异常,执行任务:{}", sysJob.getClassName());
|
||||
throw new TaskException("定时任务java反射执行异常,执行任务:" + sysJob.getClassName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.util;
|
||||
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.pig4cloud.pigx.common.core.constant.CommonConstants;
|
||||
import com.pig4cloud.pigx.daemon.quartz.entity.SysJob;
|
||||
import com.pig4cloud.pigx.daemon.quartz.exception.TaskException;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 定时任务rest反射实现
|
||||
*
|
||||
* @author 郑健楠
|
||||
*/
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
@Component("restTaskInvok")
|
||||
public class RestTaskInvok implements ITaskInvok {
|
||||
|
||||
@Override
|
||||
public void invokMethod(SysJob sysJob) throws TaskException {
|
||||
try {
|
||||
HttpRequest request = HttpUtil.createGet(sysJob.getExecutePath());
|
||||
if (sysJob.getTenantId() != null) {
|
||||
request.header(CommonConstants.TENANT_ID, sysJob.getTenantId().toString());
|
||||
}
|
||||
request.execute();
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.error("定时任务restTaskInvok异常,执行任务:{}", sysJob.getExecutePath());
|
||||
throw new TaskException("定时任务restTaskInvok业务执行失败,任务:" + sysJob.getExecutePath());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.util;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.pig4cloud.pigx.common.core.util.SpringContextHolder;
|
||||
import com.pig4cloud.pigx.daemon.quartz.constants.PigxQuartzEnum;
|
||||
import com.pig4cloud.pigx.daemon.quartz.entity.SysJob;
|
||||
import com.pig4cloud.pigx.daemon.quartz.exception.TaskException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* 定时任务spring bean反射实现
|
||||
*
|
||||
* @author 郑健楠
|
||||
*/
|
||||
@Component("springBeanTaskInvok")
|
||||
@Slf4j
|
||||
public class SpringBeanTaskInvok implements ITaskInvok {
|
||||
|
||||
@Override
|
||||
public void invokMethod(SysJob sysJob) throws TaskException {
|
||||
Object target;
|
||||
Method method;
|
||||
Object returnValue;
|
||||
// 通过Spring上下文去找 也有可能找不到
|
||||
target = SpringContextHolder.getBean(sysJob.getClassName());
|
||||
try {
|
||||
if (StrUtil.isNotEmpty(sysJob.getMethodParamsValue())) {
|
||||
method = target.getClass().getDeclaredMethod(sysJob.getMethodName(), String.class);
|
||||
ReflectionUtils.makeAccessible(method);
|
||||
returnValue = method.invoke(target, sysJob.getMethodParamsValue());
|
||||
}
|
||||
else {
|
||||
method = target.getClass().getDeclaredMethod(sysJob.getMethodName());
|
||||
ReflectionUtils.makeAccessible(method);
|
||||
returnValue = method.invoke(target);
|
||||
}
|
||||
if (StrUtil.isEmpty(returnValue.toString())
|
||||
|| PigxQuartzEnum.JOB_LOG_STATUS_FAIL.getType().equals(returnValue.toString())) {
|
||||
log.error("定时任务springBeanTaskInvok异常,执行任务:{}", sysJob.getClassName());
|
||||
throw new TaskException("定时任务springBeanTaskInvok业务执行失败,任务:" + sysJob.getClassName());
|
||||
}
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
log.error("定时任务spring bean反射异常方法未找到,执行任务:{}", sysJob.getClassName());
|
||||
throw new TaskException("定时任务spring bean反射异常方法未找到,执行任务:" + sysJob.getClassName());
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
log.error("定时任务spring bean反射异常,执行任务:{}", sysJob.getClassName());
|
||||
throw new TaskException("定时任务spring bean反射异常,执行任务:" + sysJob.getClassName());
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
log.error("定时任务spring bean反射执行异常,执行任务:{}", sysJob.getClassName());
|
||||
throw new TaskException("定时任务spring bean反射执行异常,执行任务:" + sysJob.getClassName());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.pig4cloud.pigx.daemon.quartz.util;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.pig4cloud.pigx.common.core.util.SpringContextHolder;
|
||||
import com.pig4cloud.pigx.daemon.quartz.constants.JobTypeQuartzEnum;
|
||||
import com.pig4cloud.pigx.daemon.quartz.exception.TaskException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @author Hccake
|
||||
* @version 1.0
|
||||
* @date 2019/8/8 15:40 TaskInvok工厂类
|
||||
*/
|
||||
@Slf4j
|
||||
public class TaskInvokFactory {
|
||||
|
||||
/**
|
||||
* 根据对应jobType获取对应 invoker
|
||||
* @param jobType
|
||||
* @return
|
||||
* @throws TaskException
|
||||
*/
|
||||
public static ITaskInvok getInvoker(String jobType) throws TaskException {
|
||||
if (StrUtil.isBlank(jobType)) {
|
||||
log.info("获取TaskInvok传递参数有误,jobType:{}", jobType);
|
||||
throw new TaskException("");
|
||||
}
|
||||
|
||||
ITaskInvok iTaskInvok = null;
|
||||
if (JobTypeQuartzEnum.JAVA.getType().equals(jobType)) {
|
||||
iTaskInvok = SpringContextHolder.getBean("javaClassTaskInvok");
|
||||
}
|
||||
else if (JobTypeQuartzEnum.SPRING_BEAN.getType().equals(jobType)) {
|
||||
iTaskInvok = SpringContextHolder.getBean("springBeanTaskInvok");
|
||||
}
|
||||
else if (JobTypeQuartzEnum.REST.getType().equals(jobType)) {
|
||||
iTaskInvok = SpringContextHolder.getBean("restTaskInvok");
|
||||
}
|
||||
else if (JobTypeQuartzEnum.JAR.getType().equals(jobType)) {
|
||||
iTaskInvok = SpringContextHolder.getBean("jarTaskInvok");
|
||||
}
|
||||
else if (StrUtil.isBlank(jobType)) {
|
||||
log.info("定时任务类型无对应反射方式,反射类型:{}", jobType);
|
||||
throw new TaskException("");
|
||||
}
|
||||
|
||||
return iTaskInvok;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.util;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.pig4cloud.pigx.common.data.tenant.TenantBroker;
|
||||
import com.pig4cloud.pigx.daemon.quartz.constants.PigxQuartzEnum;
|
||||
import com.pig4cloud.pigx.daemon.quartz.entity.SysJob;
|
||||
import com.pig4cloud.pigx.daemon.quartz.entity.SysJobLog;
|
||||
import com.pig4cloud.pigx.daemon.quartz.event.SysJobLogEvent;
|
||||
import com.pig4cloud.pigx.daemon.quartz.service.SysJobService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.quartz.CronTrigger;
|
||||
import org.quartz.Trigger;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.ZoneId;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 定时任务反射工具类
|
||||
*
|
||||
* @author 郑健楠
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class TaskInvokUtil {
|
||||
|
||||
private final ApplicationEventPublisher publisher;
|
||||
|
||||
private final SysJobService sysJobService;
|
||||
|
||||
@SneakyThrows
|
||||
public void invokMethod(SysJob sysJob, Trigger trigger) {
|
||||
|
||||
// 执行开始时间
|
||||
long startTime;
|
||||
// 执行结束时间
|
||||
long endTime;
|
||||
// 获取执行开始时间
|
||||
startTime = System.currentTimeMillis();
|
||||
// 更新定时任务表内的状态、执行时间、上次执行时间、下次执行时间等信息
|
||||
SysJob updateSysjob = new SysJob();
|
||||
updateSysjob.setJobId(sysJob.getJobId());
|
||||
// 日志
|
||||
SysJobLog sysJobLog = new SysJobLog();
|
||||
sysJobLog.setJobId(sysJob.getJobId());
|
||||
sysJobLog.setJobName(sysJob.getJobName());
|
||||
sysJobLog.setJobGroup(sysJob.getJobGroup());
|
||||
sysJobLog.setJobOrder(sysJob.getJobOrder());
|
||||
sysJobLog.setJobType(sysJob.getJobType());
|
||||
sysJobLog.setExecutePath(sysJob.getExecutePath());
|
||||
sysJobLog.setClassName(sysJob.getClassName());
|
||||
sysJobLog.setMethodName(sysJob.getMethodName());
|
||||
sysJobLog.setMethodParamsValue(sysJob.getMethodParamsValue());
|
||||
sysJobLog.setCronExpression(sysJob.getCronExpression());
|
||||
sysJobLog.setTenantId(sysJob.getTenantId());
|
||||
try {
|
||||
// 执行任务
|
||||
ITaskInvok iTaskInvok = TaskInvokFactory.getInvoker(sysJob.getJobType());
|
||||
// 确保租户上下文有值,使得当前线程中的多租户特性生效。
|
||||
TenantBroker.runAs(sysJob.getTenantId(), tenantId -> iTaskInvok.invokMethod(sysJob));
|
||||
|
||||
// 记录成功状态
|
||||
sysJobLog.setJobMessage(PigxQuartzEnum.JOB_LOG_STATUS_SUCCESS.getDescription());
|
||||
sysJobLog.setJobLogStatus(PigxQuartzEnum.JOB_LOG_STATUS_SUCCESS.getType());
|
||||
// 任务表信息更新
|
||||
updateSysjob.setJobExecuteStatus(PigxQuartzEnum.JOB_LOG_STATUS_SUCCESS.getType());
|
||||
}
|
||||
catch (Throwable e) {
|
||||
log.error("定时任务执行失败,任务名称:{};任务组名:{},cron执行表达式:{},执行时间:{}", sysJob.getJobName(), sysJob.getJobGroup(),
|
||||
sysJob.getCronExpression(), new Date());
|
||||
// 记录失败状态
|
||||
sysJobLog.setJobMessage(PigxQuartzEnum.JOB_LOG_STATUS_FAIL.getDescription());
|
||||
sysJobLog.setJobLogStatus(PigxQuartzEnum.JOB_LOG_STATUS_FAIL.getType());
|
||||
sysJobLog.setExceptionInfo(StrUtil.sub(e.getMessage(), 0, 2000));
|
||||
// 任务表信息更新
|
||||
updateSysjob.setJobExecuteStatus(PigxQuartzEnum.JOB_LOG_STATUS_FAIL.getType());
|
||||
}
|
||||
finally {
|
||||
// 记录执行时间 立刻执行使用的是simpleTeigger
|
||||
if (trigger instanceof CronTrigger) {
|
||||
updateSysjob.setStartTime(
|
||||
trigger.getStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
|
||||
updateSysjob.setPreviousTime(
|
||||
trigger.getPreviousFireTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
|
||||
updateSysjob.setNextTime(
|
||||
trigger.getNextFireTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
|
||||
}
|
||||
// 记录执行时长
|
||||
endTime = System.currentTimeMillis();
|
||||
sysJobLog.setExecuteTime(String.valueOf(endTime - startTime));
|
||||
|
||||
publisher.publishEvent(new SysJobLogEvent(sysJobLog));
|
||||
sysJobService.updateById(updateSysjob);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.daemon.quartz.util;
|
||||
|
||||
import com.pig4cloud.pigx.daemon.quartz.config.PigxQuartzFactory;
|
||||
import com.pig4cloud.pigx.daemon.quartz.constants.PigxQuartzEnum;
|
||||
import com.pig4cloud.pigx.daemon.quartz.entity.SysJob;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.quartz.*;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 定时任务的工具类
|
||||
*
|
||||
* @author 郑健楠
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class TaskUtil {
|
||||
|
||||
/**
|
||||
* 获取定时任务的唯一key
|
||||
* @param sysjob
|
||||
* @return
|
||||
*/
|
||||
public static JobKey getJobKey(SysJob sysjob) {
|
||||
return JobKey.jobKey(sysjob.getJobName(), sysjob.getJobGroup());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取定时任务触发器cron的唯一key
|
||||
* @param sysjob
|
||||
* @return
|
||||
*/
|
||||
public static TriggerKey getTriggerKey(SysJob sysjob) {
|
||||
return TriggerKey.triggerKey(sysjob.getJobName(), sysjob.getJobGroup());
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加或更新定时任务
|
||||
* @param sysjob
|
||||
* @param scheduler
|
||||
*/
|
||||
public void addOrUpateJob(SysJob sysjob, Scheduler scheduler) {
|
||||
CronTrigger trigger = null;
|
||||
try {
|
||||
JobKey jobKey = getJobKey(sysjob);
|
||||
// 获得触发器
|
||||
TriggerKey triggerKey = getTriggerKey(sysjob);
|
||||
trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
|
||||
// 判断触发器是否存在(如果存在说明之前运行过但是在当前被禁用了,如果不存在说明一次都没运行过)
|
||||
if (trigger == null) {
|
||||
// 新建一个工作任务 指定任务类型为串接进行的
|
||||
JobDetail jobDetail = JobBuilder.newJob(PigxQuartzFactory.class).withIdentity(jobKey).build();
|
||||
// 将任务信息添加到任务信息中
|
||||
jobDetail.getJobDataMap().put(PigxQuartzEnum.SCHEDULE_JOB_KEY.getType(), sysjob);
|
||||
// 将cron表达式进行转换
|
||||
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(sysjob.getCronExpression());
|
||||
cronScheduleBuilder = this.handleCronScheduleMisfirePolicy(sysjob, cronScheduleBuilder);
|
||||
// 创建触发器并将cron表达式对象给塞入
|
||||
trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(cronScheduleBuilder)
|
||||
.build();
|
||||
// 在调度器中将触发器和任务进行组合
|
||||
scheduler.scheduleJob(jobDetail, trigger);
|
||||
}
|
||||
else {
|
||||
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(sysjob.getCronExpression());
|
||||
cronScheduleBuilder = this.handleCronScheduleMisfirePolicy(sysjob, cronScheduleBuilder);
|
||||
// 按照新的规则进行
|
||||
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(cronScheduleBuilder)
|
||||
.build();
|
||||
// 将任务信息更新到任务信息中
|
||||
trigger.getJobDataMap().put(PigxQuartzEnum.SCHEDULE_JOB_KEY.getType(), sysjob);
|
||||
// 重启
|
||||
scheduler.rescheduleJob(triggerKey, trigger);
|
||||
}
|
||||
// 如任务状态为暂停
|
||||
if (sysjob.getJobStatus().equals(PigxQuartzEnum.JOB_STATUS_NOT_RUNNING.getType())) {
|
||||
this.pauseJob(sysjob, scheduler);
|
||||
}
|
||||
}
|
||||
catch (SchedulerException e) {
|
||||
log.error("添加或更新定时任务,失败信息:{}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 立即执行一次任务
|
||||
*/
|
||||
public static boolean runOnce(Scheduler scheduler, SysJob sysJob) {
|
||||
try {
|
||||
// 参数
|
||||
JobDataMap dataMap = new JobDataMap();
|
||||
dataMap.put(PigxQuartzEnum.SCHEDULE_JOB_KEY.getType(), sysJob);
|
||||
|
||||
scheduler.triggerJob(getJobKey(sysJob), dataMap);
|
||||
}
|
||||
catch (SchedulerException e) {
|
||||
log.error("立刻执行定时任务,失败信息:{}", e.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 暂停定时任务
|
||||
* @param sysjob
|
||||
* @param scheduler
|
||||
*/
|
||||
public void pauseJob(SysJob sysjob, Scheduler scheduler) {
|
||||
try {
|
||||
if (scheduler != null) {
|
||||
scheduler.pauseJob(getJobKey(sysjob));
|
||||
}
|
||||
}
|
||||
catch (SchedulerException e) {
|
||||
log.error("暂停任务失败,失败信息:{}", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复定时任务
|
||||
* @param sysjob
|
||||
* @param scheduler
|
||||
*/
|
||||
public void resumeJob(SysJob sysjob, Scheduler scheduler) {
|
||||
try {
|
||||
if (scheduler != null) {
|
||||
scheduler.resumeJob(getJobKey(sysjob));
|
||||
}
|
||||
}
|
||||
catch (SchedulerException e) {
|
||||
log.error("恢复任务失败,失败信息:{}", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除定时任务
|
||||
* @param sysjob
|
||||
* @param scheduler
|
||||
*/
|
||||
public void removeJob(SysJob sysjob, Scheduler scheduler) {
|
||||
try {
|
||||
if (scheduler != null) {
|
||||
// 停止触发器
|
||||
scheduler.pauseTrigger(getTriggerKey(sysjob));
|
||||
// 移除触发器
|
||||
scheduler.unscheduleJob(getTriggerKey(sysjob));
|
||||
// 删除任务
|
||||
scheduler.deleteJob(getJobKey(sysjob));
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.error("移除定时任务失败,失败信息:{}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动所有运行定时任务
|
||||
* @param scheduler
|
||||
*/
|
||||
public void startJobs(Scheduler scheduler) {
|
||||
try {
|
||||
if (scheduler != null) {
|
||||
scheduler.resumeAll();
|
||||
}
|
||||
}
|
||||
catch (SchedulerException e) {
|
||||
log.error("启动所有运行定时任务失败,失败信息:{}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止所有运行定时任务
|
||||
* @param scheduler
|
||||
*/
|
||||
public void pauseJobs(Scheduler scheduler) {
|
||||
try {
|
||||
if (scheduler != null) {
|
||||
scheduler.pauseAll();
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.error("暂停所有运行定时任务失败,失败信息:{}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取错失执行策略方法
|
||||
* @param sysJob
|
||||
* @param cronScheduleBuilder
|
||||
* @return
|
||||
*/
|
||||
private CronScheduleBuilder handleCronScheduleMisfirePolicy(SysJob sysJob,
|
||||
CronScheduleBuilder cronScheduleBuilder) {
|
||||
if (PigxQuartzEnum.MISFIRE_DEFAULT.getType().equals(sysJob.getMisfirePolicy())) {
|
||||
return cronScheduleBuilder;
|
||||
}
|
||||
else if (PigxQuartzEnum.MISFIRE_IGNORE_MISFIRES.getType().equals(sysJob.getMisfirePolicy())) {
|
||||
return cronScheduleBuilder.withMisfireHandlingInstructionIgnoreMisfires();
|
||||
}
|
||||
else if (PigxQuartzEnum.MISFIRE_FIRE_AND_PROCEED.getType().equals(sysJob.getMisfirePolicy())) {
|
||||
return cronScheduleBuilder.withMisfireHandlingInstructionFireAndProceed();
|
||||
}
|
||||
else if (PigxQuartzEnum.MISFIRE_DO_NOTHING.getType().equals(sysJob.getMisfirePolicy())) {
|
||||
return cronScheduleBuilder.withMisfireHandlingInstructionDoNothing();
|
||||
}
|
||||
else {
|
||||
return cronScheduleBuilder;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断cron表达式是否正确
|
||||
* @param cronExpression
|
||||
* @return
|
||||
*/
|
||||
public boolean isValidCron(String cronExpression) {
|
||||
return CronExpression.isValidExpression(cronExpression);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
server:
|
||||
port: 5007
|
||||
|
||||
quartz:
|
||||
enabled: true
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: @artifactId@
|
||||
cloud:
|
||||
nacos:
|
||||
username: @nacos.username@
|
||||
password: @nacos.password@
|
||||
discovery:
|
||||
server-addr: ${NACOS_HOST:pigx-register}:${NACOS_PORT:8848}
|
||||
config:
|
||||
server-addr: ${spring.cloud.nacos.discovery.server-addr}
|
||||
config:
|
||||
import:
|
||||
- optional:nacos:application-@profiles.active@.yml
|
||||
- optional:nacos:${spring.application.name}-@profiles.active@.yml
|
||||
@@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
小技巧: 在根pom里面设置统一存放路径,统一管理方便维护
|
||||
<properties>
|
||||
<log-path>/Users/lengleng</log-path>
|
||||
</properties>
|
||||
1. 其他模块加日志输出,直接copy本文件放在resources 目录即可
|
||||
2. 注意修改 <property name="${log-path}/log.path" value=""/> 的value模块
|
||||
-->
|
||||
<configuration debug="false" scan="false">
|
||||
<property name="log.path" value="logs/${project.artifactId}"/>
|
||||
<!-- 彩色日志格式 -->
|
||||
<property name="CONSOLE_LOG_PATTERN"
|
||||
value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
|
||||
<!-- 彩色日志依赖的渲染类 -->
|
||||
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
|
||||
<conversionRule conversionWord="wex"
|
||||
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
|
||||
<conversionRule conversionWord="wEx"
|
||||
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
|
||||
<!-- Console log output -->
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- Log file debug output -->
|
||||
<appender name="debug" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${log.path}/debug.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<fileNamePattern>${log.path}/%d{yyyy-MM, aux}/debug.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
|
||||
<maxFileSize>50MB</maxFileSize>
|
||||
<maxHistory>30</maxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>%date [%thread] %-5level [%logger{50}] %file:%line - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- Log file error output -->
|
||||
<appender name="error" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${log.path}/error.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<fileNamePattern>${log.path}/%d{yyyy-MM}/error.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
|
||||
<maxFileSize>50MB</maxFileSize>
|
||||
<maxHistory>30</maxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>%date [%thread] %-5level [%logger{50}] %file:%line - %msg%n</pattern>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||
<level>ERROR</level>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<logger name="org.activiti.engine.impl.db" level="DEBUG">
|
||||
<appender-ref ref="debug"/>
|
||||
</logger>
|
||||
|
||||
<!--nacos 心跳 INFO 屏蔽-->
|
||||
<logger name="com.alibaba.nacos" level="OFF">
|
||||
<appender-ref ref="error"/>
|
||||
</logger>
|
||||
<!-- Level: FATAL 0 ERROR 3 WARN 4 INFO 6 DEBUG 7 -->
|
||||
<root level="INFO">
|
||||
<appender-ref ref="console"/>
|
||||
<appender-ref ref="debug"/>
|
||||
<appender-ref ref="error"/>
|
||||
</root>
|
||||
</configuration>
|
||||
Reference in New Issue
Block a user