1、Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。这里我介绍quartz的两种方式。我这里搭建的框架是采用springboot、spring-data-jpa、mysql、quartz的方式来实现。
2、这里介绍的两种方式是:动态扫描的方式执行和注解的方式。
至于xml的配置方式可以参考:http://www.cnblogs.com/ll409546297/p/7157702.html
3、动态扫描的方式
1)基本的目录结构
2)需要的基础包:pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.troy</groupId>
<artifactId>springbootquartz</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.7.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>1.5.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>1.5.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.9</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.11.RELEASE</version>
</dependency>
</dependencies>
</project>
3)基本的yml配置application.yml
server:
port: 8080
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/model?useUnicode=true&characterEncoding=utf8
username: root
password: root
jpa:
hibernate:
ddl-auto: update
show-sql: true
4)任务配置:TaskConfiguration.class
@Configuration
@EnableScheduling
public class TaskConfiguration {
@Bean
public SchedulerFactoryBean schedulerFactoryBean(){
return new SchedulerFactoryBean();
}
}
5)实体需要的基础配置:ScheduleJob.class
@Entity
@Table
public class ScheduleJob {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String jobName;
private String cronExpression;
private String springId;
private String methodName;
private String jobStatus;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getJobName() {
return jobName;
}
public void setJobName(String jobName) {
this.jobName = jobName;
}
public String getCronExpression() {
return cronExpression;
}
public void setCronExpression(String cronExpression) {
this.cronExpression = cronExpression;
}
public String getSpringId() {
return springId;
}
public void setSpringId(String springId) {
this.springId = springId;
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
public String getJobStatus() {
return jobStatus;
}
public void setJobStatus(String jobStatus) {
this.jobStatus = jobStatus;
}
}
6)基础数据访问配置和数据访问层:
@NoRepositoryBean
public interface BaseRepository<T,I extends Serializable> extends PagingAndSortingRepository<T,I>, JpaSpecificationExecutor<T> {
}
public interface ScheduleJobRepository extends BaseRepository<ScheduleJob,Long> {
List<ScheduleJob> findAllByJobStatus(String jobStatus);
}
7)SpringUtil.class
@Component
public class SpringUtil implements BeanFactoryPostProcessor {
private static ConfigurableListableBeanFactory beanFactory;
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
public static Object getBean(String name) {
return beanFactory.getBean(name);
}
public static <T> T getBean(Class<T> clazz){
return beanFactory.getBean(clazz);
}
}
8)任务的调度工厂(主要是实现具体的执行)QuartzFactory.class
public class QuartzFactory implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
//获取调度数据
ScheduleJob scheduleJob = (ScheduleJob) jobExecutionContext.getMergedJobDataMap().get("scheduleJob");
//获取对应的Bean
Object object = SpringUtil.getBean(scheduleJob.getSpringId());
try {
//利用反射执行对应方法
Method method = object.getClass().getMethod(scheduleJob.getMethodName());
method.invoke(object);
} catch (Exception e) {
e.printStackTrace();
}
}
}
9)具体的任务调度以及触发设置:TaskServiceImpl.class(略过接口)
@Service
@Transactional
public class TaskServiceImpl implements ITaskService {
@Autowired
private SchedulerFactoryBean schedulerFactoryBean;
@Autowired
private ScheduleJobRepository scheduleJobRepository;
@Override
public void timingTask() {
//查询数据库是否存在需要定时的任务
List<ScheduleJob> scheduleJobs = scheduleJobRepository.findAllByJobStatus("1");
if (scheduleJobs != null) {
scheduleJobs.forEach(this::execute);
}
}
//添加任务
private void execute(ScheduleJob scheduleJob){
try {
//声明调度器
Scheduler scheduler = schedulerFactoryBean.getScheduler();
//添加触发调度名称
TriggerKey triggerKey = TriggerKey.triggerKey(scheduleJob.getJobName());
//设置触发时间
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression());
//触发建立
Trigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build();
//添加作业名称
JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName());
//建立作业
JobDetail jobDetail = JobBuilder.newJob(QuartzFactory.class).withIdentity(jobKey).build();
//传入调度的数据,在QuartzFactory中需要使用
jobDetail.getJobDataMap().put("scheduleJob",scheduleJob);
//调度作业
scheduler.scheduleJob(jobDetail,trigger);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
10)然后设置开机启动执行:TaskSchedule.class
@Component
public class TaskSchedule implements CommandLineRunner{
@Autowired
private ITaskService taskService;
/**
* 任务调度开始
* @param strings
* @throws Exception
*/
@Override
public void run(String... strings) throws Exception {
System.out.println("任务调度开始==============任务调度开始");
taskService.timingTask();
System.out.println("任务调度结束==============任务调度结束");
}
}
这里基础的配置就算完成了,然后就是在数据库进行相关的配置,项目启动的时候就开始扫描对应的表来执行具体的任务。
这里我写了一下简单的例子来实现。
1)需要执行的方法:TaskInfoServiceImpl.class(略过接口)
@Service("taskInfo")
@Transactional
public class TaskInfoServiceImpl implements ITaskInfoService {
@Override
public void execute() {
System.out.println("任务执行开始===============任务执行开始");
System.out.println(new Date());
System.out.println("任务执行结束===============任务执行结束");
}
}
2)数据库的配置(我这里测试用的每分钟0点执行)
测试结果:
4、注解的方式
1)注解的方式相对动态配置来说简单的多,但是不便于管理。注解的方式需要的基础包,和上面基本上差不多
2)这里我写了一下简单的例子来实现:TaskExcuteServiceImpl.class
@Service
@Transactional
public class TaskExcuteServiceImpl implements ITaskExcuteService {
@Scheduled(cron = "30 * * * * ?")
@Override
public void excute() {
System.out.println("注解执行开始==============注解执行开始");
System.out.println(new Date());
System.out.println("注解执行结束==============注解执行结束");
}
}
3)测试结果为:
5、有需要源码的可以自己下载:https://pan.baidu.com/s/1pLSLdTT
配置springMVC的定时任务可以参考我的另外一篇博客:SpringMVC 配置定时执行任务