利用quartz實現定時調度


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&amp;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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM