成人怡红院-成人怡红院视频在线观看-成人影视大全-成人影院203nnxyz-美女毛片在线看-美女免费黄

站長資訊網
最全最豐富的資訊網站

springboot+quartz 以持久化的方式實現定時任務

springboot+quartz 以持久化的方式實現定時任務

這篇文章給大家介紹springboot+quartz以持久化的方式實現定時任務,詳情如下所示:

篇幅較長,耐心的人總能得到最后的答案小生第一次用quartz做定時任務,不足之處多多諒解。

首先

在springboot項目里做定時任務是比較簡單的,最簡單的實現方式是使用**@Scheduled注解,然后在application啟動類上使用@EnableScheduling**開啟定時任務。

示例

@SpringBootApplication @EnableScheduling public class Application {   public static void main(String[] args) {  SpringApplication.run(Application.class, args);  }  // cron為每秒執行一次  @Scheduled(cron = "* * * * * ?")  public void print(){  System.out.println("執行定時任務");  }  }

######結果

執行定時任務
執行定時任務
執行定時任務
執行定時任務
執行定時任務
執行定時任務
執行定時任務
執行定時任務

簡單的定時任務就可以用這種方式來做,cron表達式的結果為任務執行的間隔時間。

然而

實際開發中,我們的任務可能有很多,且需要手動操作單個/全部的任務,比如添加、開啟、停止、繼續等等操作。那么伴隨著(千牛B類。。。)的BGM有請quartz登場。

quartz

整合

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

quartz的三要素

  • 調度器Scheduler
  • 啟動觸發器去執行任務
  • 觸發器Trigger

用來定義Job(任務)觸發條件、觸發時間,觸發間隔,終止時間等

任務job

具體要執行的任務內容

使用

使用quartz是需要配置文件的,quartz.properties在quartz的jar包的org.quartz包下可以找到默認的配置文件quartz.properties

# Default Properties file for use by StdSchedulerFactory # to create a Quartz Scheduler Instance, if a different # properties file is not explicitly specified. # # 名字 org.quartz.scheduler.instanceName: DefaultQuartzScheduler org.quartz.scheduler.rmi.export: false org.quartz.scheduler.rmi.proxy: false org.quartz.scheduler.wrapJobExecutionInUserTransaction: false # 實例化ThreadPool時,使用的線程類為SimpleThreadPool 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 # 持久化方式,默認持久化在內存中,后面我們使用db的方式 org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore

quartz任務持久化到db則需要一些官方定義的數據庫表,表的sql文件可以在quartz的jar包里找到

坐標org.quartz.impl.jdbcjobstore,可以看到里面有很多sql文件,有各種數據庫的,咱們用MySQL的,咱們不需要手動執行sql語句,后面咱們在啟動項目的時候自動初始化。

創建我們自己的properties文件

# 實例化ThreadPool時,使用的線程類為SimpleThreadPool org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool # threadCount和threadPriority將以setter的形式注入ThreadPool實例 # 并發個數 org.quartz.threadPool.threadCount=10 # 優先級 org.quartz.threadPool.threadPriority=5 org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true org.quartz.jobStore.misfireThreshold=5000 #持久化使用的類 org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX #數據庫中表的前綴 org.quartz.jobStore.tablePrefix=QRTZ_ #數據源命名 org.quartz.jobStore.dataSource=qzDS #qzDS 數據源,我們使用hikaricp,默認的是c3p0 org.quartz.dataSource.qzDS.provider=hikaricp org.quartz.dataSource.qzDS.driver=com.mysql.cj.jdbc.Driver org.quartz.dataSource.qzDS.URL=jdbc:mysql://localhost:3306/quartz?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8 org.quartz.dataSource.qzDS.user=root org.quartz.dataSource.qzDS.password=123456 org.quartz.dataSource.qzDS.maxConnections=10

既然我們沒有使用默認的連接池,那么就探索一下,上源碼!在這個包下:org.quartz.utils,有一個PoolingConnectionProvider,顧名思義,連接池提供者部分源碼

public interface PoolingConnectionProvider extends ConnectionProvider {   /** The pooling provider. */  String POOLING_PROVIDER = "provider";   /** The c3p0 pooling provider. */  String POOLING_PROVIDER_C3P0 = "c3p0";   /** The Hikari pooling provider. */  String POOLING_PROVIDER_HIKARICP = "hikaricp";  }

然后HikariCpPoolingConnectionProvider這個類實現了PoolingConnectionProvider,自行查看。我們可以在org.quartz.impl下的StdSchedulerFactory中搜索c3p0找到

if(poolingProvider != null && poolingProvider.equals(PoolingConnectionProvider.POOLING_PROVIDER_HIKARICP)) {   cpClass = "org.quartz.utils.HikariCpPoolingConnectionProvider";   }   else {   cpClass = "org.quartz.utils.C3p0PoolingConnectionProvider";   }

剩下的自己多看看吧,起始源碼研究起來沒有想象中那么難那么乏味(我也不喜歡看源碼),但是這個源碼看起來確實小有成就感。

回到正題頻道,配置application.yml

spring:  datasource:  driver-class-name: com.mysql.cj.jdbc.Driver  password: 123456  url: jdbc:mysql://localhost:3306/quartz?characterEncoding=UTF8&useSSL=false&serverTimezone=GMT%2B8  username: root  quartz:  jdbc:  initialize-schema: always  job-store-type: jdbc

initialize-schema: always每次啟動項目,總是初始化數據庫表自動創建表的關鍵地方,流程是先刪除數據庫表,再創建,如果表不存在,則拋異常,但是不會影響后面的生成表,下次再啟動項目的時候,由于表已經存在了,所以不會再拋異常了job-store-type: jdbc就是任務持久化類型,我們用jdbc

我們可能要在job里注入spring對象,不做配置,是無法注入的。

/**  * @author: taoym  * @date: 2020/6/4 11:32  * @desc: 一定要自定義JobFactory重寫SpringBeanJobFactory的createJobInstance方法,否則在job中是獲取不到spring容器中的bean的  */ @Component public class JobFactory extends SpringBeanJobFactory {   @Autowired  private AutowireCapableBeanFactory beanFactory;   /**  * 這里覆蓋了super的createJobInstance方法,對其創建出來的類再進行autowire  */  @Override  protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {  Object jobInstance = super.createJobInstance(bundle);  beanFactory.autowireBean(jobInstance);  return jobInstance;  } }

創建quartz的配置文件

@Configuration public class QuartzConfig {   @Autowired  private JobFactory jobFactory;   /**  * 讀取quartz.properties 文件  * 將值初始化  *  * @return  */  @Bean  public Properties quartzProperties() throws IOException {  PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();  propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));  propertiesFactoryBean.afterPropertiesSet();  return propertiesFactoryBean.getObject();  }   @Bean  public SchedulerFactoryBean schedulerFactoryBean() throws IOException {  SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();  schedulerFactoryBean.setJobFactory(jobFactory);  schedulerFactoryBean.setQuartzProperties(quartzProperties());  return schedulerFactoryBean;  }   /**  * 初始化監聽器  *  * @return  */  @Bean  public QuartzInitializerListener executorListener() {  return new QuartzInitializerListener();  }    @Bean(name = "scheduler")  public Scheduler scheduler() throws IOException {  return schedulerFactoryBean().getScheduler();  } }

創建觸發器組件

public class TriggerComponent {   /**  * @author: taoym  * @date: 2020/6/1 10:35  * @desc: 構建cron觸發器  */  public static Trigger cronTrigger(String cron) {  CronTrigger cronTrigger = TriggerBuilder.newTrigger()  .withSchedule(CronScheduleBuilder.cronSchedule(cron).withMisfireHandlingInstructionDoNothing())  .build();  return cronTrigger;  }   public static Trigger cronTrigger(String cron, JobDataMap jobDataMap) {  CronTrigger cronTrigger = TriggerBuilder.newTrigger()  .withSchedule(CronScheduleBuilder.cronSchedule(cron).withMisfireHandlingInstructionDoNothing())  .usingJobData(jobDataMap)  .build();  return cronTrigger;  } }

觸發器就用這個組件來獲取就行了。

創建任務

@DisallowConcurrentExecution public class TestJob extends QuartzJobBean {  @Override  protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {    } }

jobExecutionContext這里面可以獲取任務組、任務名、觸發器組、觸發器名、jobdetail等信息。那個注解是為了讓同一個實例(jobdetail)只能單線程執行。可以這么理解,job為接口,jobdetail為實現類,a是其中一個實現類,a需要花費100s執行一定的操作,而你給的定時器是沒50s就執行一次操作,a在執行到一半的時候又需要開啟一個線程來執行。使用了DisallowConcurrentExecution就相當于a沒有把操作執行完的時候,a不允許開啟線程再執行當前操作。不知道我的描述是否易懂!

按需創建自己的任務表,我是用定時任務做爬蟲的(小爬蟲)

CREATE TABLE `quartz_job` (  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '編號',  `job_name` varchar(50) DEFAULT '' COMMENT '任務名',  `job_group` varchar(50) DEFAULT '' COMMENT '任務組名稱',  `job_desc` varchar(255) DEFAULT '' COMMENT 'job描述',  `cron` varchar(50) DEFAULT '' COMMENT 'cron表達式',  `status` tinyint(1) DEFAULT '0' COMMENT '狀態',  `url` varchar(255) DEFAULT '' COMMENT '請求地址',  `param` varchar(255) DEFAULT '' COMMENT '參數',  PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8;

我們添加任務的時候不和quartz打交道,把任務放到數據庫即可。別慌,后面有用到他的地方。這個表需要有增刪改查操作,我們會在系統中查詢任務列表選擇單個或者所有任務開始執行

執行任務

@Resource  private QuartzJobMapper quartzJobMapper;  @Autowired  private Scheduler scheduler;      @Override  public String start(Integer id) {   		JobDataMap jobDataMap = new JobDataMap();  jobDataMap.put(k,v);    QuartzJob quartzJob = quartzJobMapper.selectByPrimaryKey(id);    JobKey jobKey = JobKey.jobKey(quartzJob.getJobName(), quartzJob.getJobGroup());    jobDetail = JobBuilder.newJob(TestJob.class).withIdentity(jobKey).storeDurably().build();    Trigger trigger = TriggerComponent.cronTrigger(quartzJob.getCron(), jobDataMap);  try {  scheduler.scheduleJob(jobDetail, trigger);  quartzJobMapper.updateStatus(true, id);  return "開始任務執行成功";  } catch (SchedulerException se) {  log.info("開始任務的時候發生了錯誤");  }  return "開始任務的時候發生了錯誤,請檢查日志";  }

最后我又按照此教程上的內容粘貼了一遍代碼,可以正常運行。

springboot+quartz 以持久化的方式實現定時任務

springboot+quartz 以持久化的方式實現定時任務

springboot+quartz 以持久化的方式實現定時任務

springboot+quartz 以持久化的方式實現定時任務

springboot+quartz 以持久化的方式實現定時任務

推薦教程:《PHP》

贊(0)
分享到: 更多 (0)
?
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
国产男男GaYGaY无套| 跟40岁的少妇做一次就不硬了| 日韩AV无码中文无码不卡电影| 黑料社ZZTT.WIN免费观看| 国偷自产一区二视频观看| 99国产精品自在自在久久| 亚洲日韩精品无码一区二区三区 | 人妻精品久久无码区| 日韩人妻无码精品无码中文字幕| 欧美日韩人妻精品一区在线| 国内偷拍亚洲欧洲2018| 久久久久久久精品免费久精品蜜桃| 麻豆精品一区综合AV在线| 性色AV免费网站| 欧美粗大猛烈老熟妇| 一边下奶一边吃面膜视频讲解图片| 久久自己只精产国品| 98久9在线 | 免费| 成人无码免费一区二区三区| 搡老女人老妇老熟女hd| 亚洲精品偷拍区偷拍无码| 欧美精产国品一二三产品工艺| 日本熟妇人妻XXXX| 欧美日韩精品人妻二区| 久久国产精品无码一区二区三区| 肥胖BMGBMGBMG多毛图片| 国产三级精品三级在线专区1| 娇妻卧室含辱迎接领导是哪部电影| 成人无码H动漫在线网站樱花| 国产精品三级在线观看无码| 久久er99热精品一区二区| 欧美丰满熟妇乱XXXXX流白浆| 成人免费无码不卡毛片| 国产成人综合久久精品推最新| WC女厕撒尿七Ⅴ偷拍| 国产精品久久久久精品香蕉爆乳| 大乳VIDEOS巨大吃奶| 国产一区二区三区不卡在线观看 | 免费看老外操B视频| 日韩一区二区三区无码人妻视频| 亚洲AV乱码一区二区三区按摩| 在线VA无码中文字幕| 国产99在线 | 免费| 久久精品国产欧美日韩| 久久久久夜夜夜综合国产| 日产精品卡二卡三卡四卡区| 亚洲精品无码乱码成人爱色| xxxxxx日本黄色| 成人免费A级毛片天天看| 韩国电影理伦片完整| 欧美人与动牲交A免费| 亚洲AV日韩AV无码AV| 中中文日产幕无线码一区| JAPANESE 大战黑人| 24小时最新在线视频免费观看| 无码欧精品亚洲日韩一区| 日本一本免费一区二区三区免| 妺妺坐在我腿上勃起弄了应用| 女教师办公室被强在线播放| 亚洲香蕉成人AV网站在线观看| 两个病娇男友轮流爱我资源| 精品国产制服丝袜高跟| 日本狂喷奶水在线播放212| 亚洲娇小被黑人巨大撑爆| 成人无码专区免费播放三区| 久久久久久AV无码免费网站下载| 上司侵犯部下的人妻| 中文字幕人成乱码中国| 国产一区二区三区影院| 日本A级视频在线播放| 亚洲综合网站精品一区二区| 一炕四女被窝交换啪啪| 国产成人AV在线影院| 女朋友特别闷骚很吸引别人| 亚洲国产AV玩弄放荡人妇系列| 与子乱刺激对白在线播放| 国产精品一区二区水蜜桃色欲| 欧洲VODAFONEWIFI喷| 一本加勒比HEZYO无码人妻| JAPANESETUBE日本护| 久久国产成人精品国产成人亚洲| 污的你下面一直滴水的句子| 阿公抱着我边摸边吃奶视频| 脔到她哭H粗话HWWW男男动漫| 亚洲AV无码一区二区二三区入口| 中国人熟女HDFREEHDXⅩ| 国精产品一区一区三区M| 上面一个奶下面一个顶是什么字| B里可以放多少个鸡蛋| 国产精品天干天干在线综合 | 中文无码人妻影音先锋| 狠狠婷婷色五月中文字幕| 无码AV一区二区三区不卡| 亚洲色18禁成人网站WWW永久| 国产精品亚洲А∨天堂2018| 日韩乱码人妻无码中文字幕久久| 97AV麻豆蜜桃一区二区| 久久香港三级台湾三级播放| 亚洲精品TV久久久久久久久久 | 玩肥熟老妇BBWXXX视频| 成午夜福利人试看120秒| 欧美在线 | 亚洲| 2019日韩中文字幕MV| 久久婷婷六月综合色液啪| 亚洲欧洲美洲无码精品VA| 欧美变态口味重另类在线视频| 亚洲精品色午夜无码专区日韩| 精品无码人妻被多人侵犯AV| 少妇高潮太爽了在线观看欧美| 在线观看的AV网站| 国产精品成人久久电影| 野花高清完整版免费观看视频大全 | 中文字幕AV无码一二三区电影| 国产激情久久久久影院蜜桃AV| 欧美疯狂做受XXXX高潮小说| 亚洲成AV人片不卡无苍井空| 第九理论午夜电影院| 久久国产乱子精品免费女 | 午夜成人理论福利片| 中文成人无码精品久久久不卡| 国产精品免费AV片在线观看| 色老99久久精品偷偷鲁| 岳今晚让我玩个够肥水一体探岳| 裸体欣赏ⅤIDE0SPH0TO| 69风韵老熟女口爆吞精| 欧美午夜性春猛交ⅩXXX| 荫道BBWBBB高潮潮喷| 国产成人无码AV在线播放无广告| 精品亚洲国产成人蜜臀优播AV| 丝袜人妻无码中文字幕综合网| 在线日韩日本国产亚洲| 国产麻传媒精品国产AV| 人妻中文字幕制服丝袜| 淫荡集团69视频在线观看| 国内精品久久久久久中文字幕| 日本AⅤ精品一区二区三区日| 伊人久久大香线蕉AV波多野结衣 | 欧美乱大交XXXXX| 性少妇JEALOUSVUE成熟| 国模少妇一区二区三区| 亚洲国产成人精品无码区在线| 精品国产麻豆免费人成网站| 亚洲无人区码一码二码三码区别| 久久久久久亚洲精品中文字幕| 亚洲一区二区三区日本久久九| 久久精品国产99国产精2020| 在办公室伦流澡到高潮H| 欧美精品天堂一区二区不卡| 宝贝把腿张开我要添你下边动态图| 日韩欧美中文字幕看片你懂的| 国产V亚洲V欧美V专区| 性色AV无码久久一区二区三区| 和老婆一起玩的双人| 亚洲综合一区二区三区四区五区 | 三上悠亚AV资源站| 国产精品成人影院久久久| 亚洲AV无码乱码在线观看牲色| 久久精品亚洲乱码伦伦中文| 中文字幕一区二区三区久久网站 | 野花韩国视频免费高清3| 亚洲AV无码专区亚洲AV桃| 一二三四视频中文字幕在线看| 娇小美女被黑壮汉C到喷水| 亚洲AV成人午夜亚洲美女| 狠狠色噜噜狠狠狠狠AV不卡| 欧美ZC0O人与善交的最新章节| 在线观看一区二区三区AV| 強暴強姦AV正片一区二区| 久久99国产精品久久99蜜桃| 日本COSME大赏美白| 国产成人午夜在线视频A站 | 国产2021在线传媒麻豆| 亚洲AV无码成人精品区浪潮AV| 久久久国产99久久国产久| 99久久免费国产精品四虎99久久精品免费看国产一区二区 | 黑人顶到深处高潮颤抖| 一边下奶一边吃面膜视频| 人妻在厨房被色诱 中文字幕| 国产精品露脸国语对白| 亚洲欧洲日产国码无码| 女神被啪进深处娇喘在线观看 | 精品国产一区二区三区2021| 18禁无遮挡羞羞啪啪免费网站| 日日摸日日碰夜夜爽无| 狠狠色噜噜狠狠狠777米奇小说| 中文字幕精品久久久久人妻| 上面一边亲下一边面膜使用方法| 国产无遮挡又黄又爽又色| JAVASCRIPTJAVA成熟亲子| 少妇扒开毛茸茸的B自慰| 国产精品一国产精品一K频道| 亚洲系列精品少妇系列50P| 人妻AV一区二区| 久久99精品久久久久蜜芽| 久久天堂AV女色优精品| 欧亚精品一区三区免费| 亚洲AV成人一区二区三区天堂 | 无人区码一码二码三码网页| 狠狠色丁香久久综合| 疯狂做受XXXX高潮不断|