Skip to content

Commit

Permalink
✨ 增加Quartz定时任务starter
Browse files Browse the repository at this point in the history
  • Loading branch information
evil0th authored and Hccake committed May 16, 2024
1 parent 93a287f commit 3efed51
Show file tree
Hide file tree
Showing 24 changed files with 1,631 additions and 2 deletions.
3 changes: 1 addition & 2 deletions ballcat-parent/src/checkstyle/checkstyle-suppressions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
<suppress files="org.bson.types.ObjectId" checks="[a-zA-Z0-9]*" />
<suppress files="com.alibaba.excel.*.*\.java" checks="[a-zA-Z0-9]*" />

<suppress files="org.ballcat.easyexcel.application.ExcelTestApplication" checks="HideUtilityClassConstructorCheck" />
<suppress files="org.ballcat.autoconfigure.web.TestApplication" checks="HideUtilityClassConstructorCheck" />
<suppress files="org.ballcat.*.*TestApplication" checks="HideUtilityClassConstructorCheck" />
<suppress files="org.ballcat.pay.wx.domain.DefaultWxDomain" checks="FinalClassCheck" />
<suppress files="org.ballcat.autoconfigure.redis.RedisKeyEventAutoConfiguration" checks="HideUtilityClassConstructorCheck" />
</suppressions>
49 changes: 49 additions & 0 deletions job/ballcat-spring-boot-starter-quartz/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?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>org.ballcat</groupId>
<artifactId>ballcat-parent</artifactId>
<version>${revision}</version>
<relativePath>../../ballcat-parent</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ballcat-spring-boot-starter-quartz</artifactId>

<dependencies>
<dependency>
<groupId>org.ballcat</groupId>
<artifactId>ballcat-common-util</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
<optional>true</optional>
</dependency>

<!--mysql驱动-->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* Copyright 2023-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.ballcat.autoconfigure.quartz;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;

import lombok.extern.slf4j.Slf4j;
import org.ballcat.autoconfigure.quartz.constants.JobConstant;
import org.ballcat.autoconfigure.quartz.event.listener.JobExecuteTraceStoreListener;
import org.ballcat.autoconfigure.quartz.job.CleanExecuteTraceJob;
import org.ballcat.autoconfigure.quartz.properties.QuartzJobProperties;
import org.ballcat.autoconfigure.quartz.service.QuartzJobService;
import org.ballcat.autoconfigure.quartz.service.impl.QuartzJobServiceImpl;
import org.ballcat.autoconfigure.quartz.store.JobExecuteTraceStore;
import org.ballcat.autoconfigure.quartz.store.impl.JdbcJobExecuteTraceStore;
import org.quartz.Scheduler;
import org.quartz.spi.SchedulerPlugin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration;
import org.springframework.boot.autoconfigure.quartz.QuartzProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;

/**
* quartz 自动装配
*
* @author evil0th Create on 2024/5/8
*/
@Slf4j
@EnableAsync
@AutoConfiguration
@AutoConfigureAfter(QuartzAutoConfiguration.class)
@EnableConfigurationProperties(QuartzJobProperties.class)
@ConditionalOnProperty(prefix = QuartzJobProperties.PREFIX, name = "enabled", havingValue = "true",
matchIfMissing = true)
public class QuartzJobAutoConfiguration {

private static final Logger LOGGER = LoggerFactory.getLogger(QuartzJobAutoConfiguration.class);

@Bean
public QuartzJobService quartzJobService(Scheduler scheduler) {
return new QuartzJobServiceImpl(scheduler);
}

/**
* 配置了插件则响应存储组件要初始化 同时添加清理历史数据的任务
* 下游可以实现{@link JobExecuteTraceStore}接口和{@link SchedulerPlugin}来自定义存储
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnSingleCandidate(DataSource.class)
@ConditionalOnProperty(prefix = "spring.quartz", name = "job-store-type", havingValue = "jdbc")
static class JobExecuteTraceStoreConfiguration {

/**
* 提供默认jdbc存储实现
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = JobConstant.DEFAULT_STORE_JOB_HISTORY_PLUGIN_PROPERTIES_PREFIX, name = "class",
havingValue = JobConstant.DEFAULT_STORE_JOB_HISTORY_PLUGIN_CLASS)
public JobExecuteTraceStore jdbcJobExecuteTraceStore(DataSource dataSource) {
return new JdbcJobExecuteTraceStore(dataSource);
}

/**
* 定制了清理 cron 配置
*/
@Bean
@ConditionalOnBean(JobExecuteTraceStore.class)
@ConditionalOnProperty(prefix = JobConstant.DEFAULT_STORE_JOB_HISTORY_PLUGIN_PROPERTIES_PREFIX,
name = "cleanCron")
public JobExecuteTraceStoreListener jobExecuteTraceStoreListener(JobExecuteTraceStore jobExecuteTraceStore,
QuartzJobService quartzJobService, QuartzProperties quartzProperties) {
// 按Cron表达式执行清理历史数据Job
final String cron = quartzProperties.getProperties()
.get(JobConstant.PLUGIN_PROPERTIES_PREFIX + "." + JobConstant.DEFAULT_STORE_JOB_HISTORY_PLUGIN_NAME
+ ".cleanCron");
// 默认清理30天以前的历史数据
final int cleanDays = Integer.parseInt(quartzProperties.getProperties()
.getOrDefault(JobConstant.PLUGIN_PROPERTIES_PREFIX + "."
+ JobConstant.DEFAULT_STORE_JOB_HISTORY_PLUGIN_NAME + ".cleanDays", "30"));
Map<String, Object> params = new HashMap<>();
params.put("cleanDays", cleanDays);
Date latest = quartzJobService.addJob(CleanExecuteTraceJob.class,
JobConstant.DEFAULT_STORE_JOB_HISTORY_PLUGIN_NAME + "CleanJob", JobConstant.RESERVED_JOB_GROUP,
params, cron, null);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("[定时清理任务{}天前历史记录]初始化, CRON={}, 下一次任务执行的开始时间{}", cleanDays, cron, latest);
}
return new JobExecuteTraceStoreListener(jobExecuteTraceStore);
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright 2023-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.ballcat.autoconfigure.quartz.constants;

/**
* Quartz 常量
*
* @author evil0th Create on 2024/5/13
*/
public final class JobConstant {

private JobConstant() {
}

/**
* 保留Job分组
*/
public static final String RESERVED_JOB_GROUP = "ReservedJobGroup";

public static final String QUARTZ_PROPERTIES_PREFIX = "spring.quartz.properties";

/**
* quartz插件配置前缀
*/
public static final String PLUGIN_PROPERTIES_PREFIX = "org.quartz.plugin";

public static final String DEFAULT_STORE_JOB_HISTORY_PLUGIN_NAME = "storeJobHistory";

public static final String DEFAULT_STORE_JOB_HISTORY_PLUGIN_PROPERTIES_PREFIX = QUARTZ_PROPERTIES_PREFIX + "."
+ PLUGIN_PROPERTIES_PREFIX + "." + DEFAULT_STORE_JOB_HISTORY_PLUGIN_NAME;

public static final String DEFAULT_STORE_JOB_HISTORY_PLUGIN_CLASS = "org.ballcat.autoconfigure.quartz.plugin.StoreJobHistoryPlugin";

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright 2023-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.ballcat.autoconfigure.quartz.enums;

/**
* 任务执行记录事件类型
*
* @author evil0th Create on 2024/5/8
*/
public enum JobExecuteTraceType {

INITIALIZE, UPDATE

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright 2023-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.ballcat.autoconfigure.quartz.enums;

/**
* 任务执行记录阶段
*
* @author evil0th Create on 2024/5/8
*/
public enum JobStage {

EXECUTING, FINISHED, EXCEPTION

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2023-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.ballcat.autoconfigure.quartz.event;

import lombok.Getter;
import lombok.Setter;
import org.ballcat.autoconfigure.quartz.enums.JobExecuteTraceType;
import org.ballcat.autoconfigure.quartz.store.JobExecuteTrace;
import org.springframework.context.ApplicationEvent;

/**
* 任务执行记录事件
*
* @author evil0th Create on 2024/5/8
*/
@Getter
@Setter
public class JobExecuteTraceEvent extends ApplicationEvent {

private static final long serialVersionUID = 1L;

private final JobExecuteTrace jobExecuteTrace;

private JobExecuteTraceType eventType;

/**
* @param jobExecuteTrace JobExecuteTrace
* @param eventType {@link JobExecuteTraceType}
*/
public JobExecuteTraceEvent(JobExecuteTrace jobExecuteTrace, JobExecuteTraceType eventType) {
super(jobExecuteTrace.getJobName());
this.jobExecuteTrace = jobExecuteTrace;
this.eventType = eventType;
}

}
Loading

0 comments on commit 3efed51

Please sign in to comment.