springbatch 和 quartz 处理job框架

一款轻量的、全面的批处理框架,用于开发强大的日常运营的企业级批处理应用程序。

在大型企业中,由于业务复杂、数据量大、数据格式不同、数据交互格式繁杂,并非所有的操作都能通过交互界面进行处理。而有一些操作需要定期读取大批量的数据,然后进行一系列的后续处理。这样的过程就是“批处理”。
典型的批处理流程是读数据、处理数据、写数据的三步式架构——从数据库、文件或队列中读取大量数据,然后通过业务规则处理数据,最后将处理完的数据按需求方式写(数据库、文件等)。通常Spring Batch工作在离线模式下,不需要用户干预、就能自动进行基本的批处理迭代,进行类似事务方式的处理。

注意Spring Batch并不提供定时之类的功能,那是quartz等一些调度框架做的事情,它们是协作关系,而不是取代。它是批处理框架,quartz 是任务调度框架

主要是job 和step :

job是有一组step组成

1 依赖

<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.11</version>
		</dependency>

	<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-batch</artifactId>
		</dependency>

2 配置

spring.datasource.username=root
spring.datasource.password=1234
spring.datasource.url=jdbc:mysql://127.0.0.1/abcd?serverTimezone=GMT
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.batch.initialize-schema=always

#job 启动时候不执行
spring.batch.job.enabled=false

3 demo

@Configuration
@EnableBatchProcessing
public class JobStudy {
    @Autowired
    JobBuilderFactory jobBuilderFactory;
    
    @Autowired
    StepBuilderFactory stepBuilderFactory;
    
    @Bean
    public Job job1(){
        /**
         * 这里实现了三个step
         */
//        return jobBuilderFactory.get("job1").start(step1()).next(step2()).next(step3()).build();
        return jobBuilderFactory.get("job1").start(step1())
                .on("COMPLETED").to(step2()).from(step2()).on("COMPLETED")
                .to(step3()).end().build();//自己写顺序
        
        
    }
    
    private Step step3() {
        
        return stepBuilderFactory.get("step3333").tasklet(new Tasklet() {
            @Override
            public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) 
throws Exception {
                System.out.println("step3333");
                return RepeatStatus.FINISHED;//这里是结束状态
            }
        }).build();
    }
    
    private Step step2() {
        
        return stepBuilderFactory.get("step2222").tasklet(new Tasklet() {
            @Override
            public RepeatStatus execute(StepContribution contribution, ChunkContext 
chunkContext) throws Exception {
                System.out.println("step2222");
                return RepeatStatus.FINISHED;//这里是结束状态
            }
        }).build();
    }
    
    public Step step1() {
        
        return stepBuilderFactory.get("step111").tasklet(new Tasklet() {
            @Override
            public RepeatStatus execute(StepContribution contribution, ChunkContext 
chunkContext) throws Exception {
                System.out.println("step1111");
                return RepeatStatus.FINISHED;//这里是结束状态
            }
        }).build();
    }
    
    
}

 

quartz

下载

三个核心组件

任务job

触发器trigger

调度器scheduler

Quartz API的关键接口是:

Scheduler - 与调度程序交互的主要API。
Job - 由希望由调度程序执行的组件实现的接口。
JobDetail - 用于定义作业的实例。
Trigger(即触发器) - 定义执行给定作业的计划的组件。
JobBuilder - 用于定义/构建JobDetail实例,用于定义作业的实例。
TriggerBuilder - 用于定义/构建触发器实例。
Scheduler的生命期,从SchedulerFactory创建它时开始,到Scheduler调用shutdown()方法时结束;
Scheduler被创建后,可以增加、删除和列举Job和Trigger,以及执行其它与调度相关的操作(如暂停
Trigger)。但是,Scheduler只有在调用start()方法后,才会真正地触发trigger(即执行job)

1 依赖

   <!--quartz 依赖-->
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz-jobs</artifactId>
            <version>2.2.1</version>
        </dependency>

2 job

public class HelloJob implements Job{
    
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        System.out.println(new Date());
        System.out.println("正则抓取job");
    }
}

3 执行job

public class Main {
    
    public static void main(String[] args) throws Exception{
//       1 调度器 Schedual
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

//       2任务实例(jobDetail)  myJob任务的唯一标示
    
        JobDetail build = JobBuilder.newJob(HelloJob.class).withIdentity("myJob", 
"group1").build();

//        3触发器(trigger)
        SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", 
"group1").startNow().
                
                withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5)).build();
//        4关联job实例和触发器
        scheduler.scheduleJob(build,trigger);
//        5启动
        scheduler.start(); //结果每隔5秒执行一次
    }
}

组件介绍

job 工作任务调度的接口 ,每次执行excute方法都会创建实例

JobDetail实例是通过JobBuilder类创建的,为job实例提供许多设置属性

如:jobDetail.getDescription();

JobExecutionContext 执行的时候 获取上下文运行环境
jobExecutionContext.getJobDetail().getKey().getGroup();

JobDataMap JobDataMap中可以包含不限量的(序列化的)数据对象,在job实例执行的时候,可以使用其中的数据;
1 写入数据
 JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)
                .withIdentity("myJob", "group1")
                .usingJobData("mess","打印日志")
                .build();
 SimpleTrigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("trigger1", "group1")
                .usingJobData("message","触发器")  //传递参数
                .startNow().
                 withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5)).build();
2 获得数据 (从job中)
 @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
        String mess = jobDataMap.getString("mess");
        System.out.println(mess+"从jobDetail中获取");
        JobDataMap trigger = jobExecutionContext.getTrigger().getJobDataMap();
        String message = trigger.getString("message");
System.out.println(jobExecutionContext.getFireTime());//当前任务执行时间
System.out.println(jobExecutionContext.getNextFireTime());//下次任务执行时间
有状态job 每一次执行都会进行持久化操作,无状态job 每次一执行都会从新创建新的job

@PersistJobDataAfterExecution       //有状态
public class HelloJob implements Job{
Trigger的触发器 trigger的公共属性有:
jobKey属性:当trigger触发时被执行的job的身份;
tartTime属性:设置trigger第一次触发的时间;
endTime属性:表示trigger失效的时间点。

    Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("trigger1", "group1")
                .usingJobData("message","触发器")  //传递参数
                .startAt(new Date())  //任务开始时间
               .endAt(new Date())    //任务结束时间
                 .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5)).build();

CronTrigger通常比Simple Trigger更有用

   CronTrigger build = TriggerBuilder.newTrigger()
                .withIdentity("trigger1", "group1")
                .startNow()
                .withSchedule(CronScheduleBuilder.cronSchedule("* * * * * ?")).build();

指定时间   simple 触发器

指定时间 CronTrigger

StdSchedulerFactory是org.quartz.SchedulerFactory接口的一个实现。它使用一组属性
(java.util.Properties)来创建和初始化Quartz Scheduler。

 public static Scheduler getDefaultScheduler() throws SchedulerException {
        StdSchedulerFactory fact = new StdSchedulerFactory();

        return fact.getScheduler();
    }

任务的挂起

scheduler.standby();

Thread.sleep(2000);
scheduler.start() 两秒后继续启动

        scheduler.shutdown(true);// job执行完,在关闭scheduler
        scheduler.shutdown(false);//  直接关闭scheduler

配置文件 

org.quartz.scheduler.instanceName: DefaultQuartzScheduler
org.quartz.scheduler.rmi.export: false
org.quartz.scheduler.rmi.proxy: false
org.quartz.scheduler.wrapJobExecutionInUserTransaction: false

org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 10
org.quartz.threadPool.threadPriority: 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true

org.quartz.jobStore.misfireThreshold: 60000

org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore
监听

TriggerListeners和JobListeners

JobListeners 其中:

1) getName方法:用于获取该JobListener的名称。

2) jobToBeExecuted方法:Scheduler在JobDetail将要被执行时调用这个方法。

3) jobExecutionVetoed方法:Scheduler在JobDetail即将被执行,但又被TriggerListerner否决时会调用该方法

4) jobWasExecuted方法:Scheduler在JobDetail被执行之后调用这个方法


public class JobListenerDemo implements JobListener {
    
    @Override
    public String getName() {
        String name = getClass().getSimpleName();
        return name;
    }
    
    @Override
    public void jobToBeExecuted(JobExecutionContext context) {
        String name = context.getJobDetail().getKey().getName();
        System.out.println("jobDetail 执行前调用"+name);
    
    }
    
    @Override
    public void jobExecutionVetoed(JobExecutionContext context) {
        String name = context.getJobDetail().getKey().getName();
        System.out.println("jobDetail 执行前调用"+name);
    }
    
    @Override
    public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
        String name = context.getJobDetail().getKey().getName();
        System.out.println("jobDetail 执行后"+name);
    }

 scheduler.getListenerManager().addJobListener(new JobListenerDemo(), 
 EverythingMatcher.allJobs());//全局job

scheduler.getListenerManager().addJobListener(new JobListenerDemo(), 
KeyMatcher.keyEquals(JobKey.jobKey("myJob", "group1"))); //局部job


TriggerListeners

1) getName方法:用于获取触发器的名称

2) triggerFired方法:当与监听器相关联的Trigger被触发,Job上的execute()方法将被执行时,
Scheduler就调用该方法。

3) vetoJobExecution方法:在 Trigger 触发后,Job 将要被执行时由 Scheduler 调用这个方法。
TriggerListener 给了一个选择去否决 Job 的执行。假如这个方法返回 true,这个 Job 将不会为此次 
Trigger 触发而得到执行。

4) triggerMisfired方法:Scheduler 调用这个方法是在 Trigger 错过触发时。你应该关注此方法中持续

时间长的逻辑:在出现许多错过触发的 Trigger 时,长逻辑会导致骨牌效应。你应当保持这上方法尽量的小。

5) triggerComplete方法:Trigger 被触发并且完成了 Job 的执行时,Scheduler 调用这个方法。


//        scheduler.getListenerManager().addTriggerListener(new 
TriggerListeners(),EverythingMatcher.allTriggers()); //全局

 

SchedulerListener
SchedulerListener会在Scheduler的生命周期中关键事件发生时被调用。与Scheduler有关的事件包括:增加一
个job/trigger,删除一个job/trigger,scheduler发生严重错误,关闭scheduler等。

1) jobScheduled方法:用于部署JobDetail时调用

2) jobUnscheduled方法:用于卸载JobDetail时调用

3) triggerFinalized方法:当一个 Trigger 来到了再也不会触发的状态时调用这个方法。除非这个 Job 已设
置成了持久性,否则它就会从 Scheduler 中移除。

4) triggersPaused方法:Scheduler 调用这个方法是发生在一个 Trigger 或 Trigger 组被暂停时。假如是
 Trigger 组的话,triggerName 参数将为 null。

5) triggersResumed方法:Scheduler 调用这个方法是发生成一个 Trigger 或 Trigger 组从暂停中恢复
时。假如是 Trigger 组的话,假如是 Trigger 组的话,triggerName 参数将为 null。参数将为 null。
6) jobsPaused方法:当一个或一组 JobDetail 暂停时调用这个方法。
7) jobsResumed方法:当一个或一组 Job 从暂停上恢复时调用这个方法。假如是一个 Job 组,jobName 参数
将为 null。
8) schedulerError方法:在 Scheduler 的正常运行期间产生一个严重错误时调用这个方法。
9) schedulerStarted方法:当Scheduler 开启时,调用该方法
10) schedulerInStandbyMode方法: 当Scheduler处于StandBy模式时,调用该方法
11) schedulerShutdown方法:当Scheduler停止时,调用该方法
12) schedulingDataCleared方法:当Scheduler中的数据被清除时,调用该方法。

添加  scheduler.getListenerManager().addSchedulerListener(new Schedual());

移除 

  • 1
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值