在Spring中使用JDBCJobStore配置Quartz

我將開始一些有關Quartz Scheduler內部,提示和技巧的系列文章,這是第0章-如何配置持久性作業存儲。 在Quartz中,您基本上可以在將作業和觸發器存儲在內存中以及在關系數據庫中進行選擇( Terracotta是最近添加的混合功能)。 我想說在90%的情況下,當您將Quartz與RAMJobStore一起使用時,您根本就不需要Quartz。 顯然,此存儲后端是瞬態的,并且所有重啟之間都將丟失所有待處理的作業和觸發器。 如果您對此感到滿意,則可以使用更簡單,更輕便的解決方案,包括JDK中內置的ScheduledExecutorService和Spring中的@Scheduled(cron =” * / 5 * * * * MON-FRI”)。 您能證明在這種情況下使用額外的0.5MiB JAR是合理的嗎?

當您需要群集,故障轉移,負載平衡和其他一些時髦的詞時,情況將發生巨大變化。 有幾個用例:

  • 單個服務器無法處理所需數量的并發且長時間運行的作業,并且執行需要分成幾臺機器-但是每個任務必須完全執行
  • 我們負擔不起為時過晚的工作-如果一臺服務器宕機,另一臺服務器應按時運行
  • …或更嚴格地說–作業最終需要運行–即使只有一臺服務器因維護而停機,延遲的作業也需要在重新啟動后盡快運行

在上述所有情況下,我們都需要某種非瞬態全局存儲來跟蹤執行了哪些作業,以便它們由一臺機器精確地運行。 關系數據庫作為共享內存在這種情況下效果很好。

因此,如果您認為需要安排工作并滿足上述一些要求,請繼續閱讀。 我將向您展示如何使用Spring配置Quartz并將其完全集成。 首先我們需要一個數據源:

import org.apache.commons.dbcp.BasicDataSource
import com.googlecode.flyway.core.Flyway
import org.jdbcdslog.DataSourceProxy
import org.springframework.jdbc.datasource.{DataSourceTransactionManager, LazyConnectionDataSourceProxy}
import org.h2.Driver@Configuration
@EnableTransactionManagement
class Persistence {@Beandef transactionManager() = new DataSourceTransactionManager(dataSource())@Bean@Primarydef dataSource() = {val proxy = new DataSourceProxy()proxy.setTargetDSDirect(dbcpDataSource())new LazyConnectionDataSourceProxy(proxy)}@Bean(destroyMethod = "close")def dbcpDataSource() = {val dataSource = new BasicDataSourcedataSource.setDriverClassName(classOf[Driver].getName)dataSource.setUrl("jdbc:h2:mem:quartz-demo;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MVCC=TRUE")dataSource.setUsername("sa")dataSource.setPassword("")dataSource.setMaxActive(20)dataSource.setMaxIdle(20)dataSource.setMaxWait(10000)dataSource.setInitialSize(5)dataSource.setValidationQuery("SELECT 1")dataSource}}

您可能已經猜到了,Quartz需要一些數據庫表才能使用。 它不會自動創建它們,但是提供了幾個數據庫的SQL腳本,包括H2,您可以看到我正在使用它。 我認為Flyway是啟動時運行數據庫腳本的最簡單方法:

@Bean(initMethod = "migrate")
def flyway() = {val fly = new Flyway()fly.setDataSource(dataSource())fly
}

順便說一句,如果您沒有注意到:否,我們的示例應用程序中沒有XML,是的,我們正在使用Spring。

讓我們繼續到Quartz:

@Configuration
class Scheduling {@Resourceval persistence: Persistence = null@Bean@DependsOn(Array("flyway"))def schedulerFactory() = {val schedulerFactoryBean = new SchedulerFactoryBean()schedulerFactoryBean.setDataSource(persistence.dataSource())schedulerFactoryBean.setTransactionManager(persistence.transactionManager())schedulerFactoryBean.setConfigLocation(new ClassPathResource("quartz.properties"))schedulerFactoryBean.setJobFactory(jobFactory())schedulerFactoryBean.setApplicationContextSchedulerContextKey("applicationContext")schedulerFactoryBean.setSchedulerContextAsMap(Map().asJava)schedulerFactoryBean.setWaitForJobsToCompleteOnShutdown(true)schedulerFactoryBean}@Beandef jobFactory() = new SpringBeanJobFactory}

很高興知道您可以將@Configuration注釋類的實例注入到另一個此類中,以方便使用。 除此之外–沒有幻想。 請注意,我們需要在Quartz調度程序工廠上使用@DependsOn(Array(“ flyway”))–否則,調度程序可能會在Flyway用Quartz數據庫表觸發遷移腳本之前啟動,從而導致啟動時出現令人不愉快的錯誤。 基本位是SpringBeanJobFactory和schedulerContextAsMap。 特殊工廠使Spring負責創建Job實例。 不幸的是,這個工廠非常有限,我們將在下面的示例中很快看到。 首先,我們需要一個Spring bean和一個Quartz作業:

@Service
class Printer extends Logging {def print(msg: String) {logger.info(msg)}}class PrintMessageJob extends Job with Logging {@BeanPropertyvar printer: Printer = _@BeanPropertyvar msg = ""def execute(context: JobExecutionContext) {printer print msg}
}

第一個意外輸入是@BeanProperty,而不是@Autowired或@Resource。 事實證明,即使Job創建了一個實例,Job也不是真正的Spring bean。 相反,Spring使用可用的setter查找所需的依賴項。 那么味精字符串從何而來? 繼續:

val trigger = newTrigger().withIdentity("Every-few-seconds", "Demo").withSchedule(simpleSchedule().withIntervalInSeconds(4).repeatForever()).build()val job = newJob(classOf[PrintMessageJob]).withIdentity("Print-message", "Demo").usingJobData("msg", "Hello, world!").build()scheduler.scheduleJob(job, trigger)

Quartz 2.0附帶了一個不錯的內部DSL,用于以可讀的方式創建作業和觸發器。 如您所見,我正在傳遞一個額外的“你好,世界!” 工作參數。 該參數存儲在每個作業或每個觸發器的數據庫中所謂的JobData中。 執行時將提供給作業。 這樣,您就可以參數化您的工作。 但是,執行時,我們的作業將引發NullPointerException…顯然沒有設置打印機引用,并且忽略了該引用。 事實證明,Spring不會簡單地瀏覽ApplicationContext中所有可用的bean。 SpringBeanJobFactory僅查看Jobs和Triggers的JobData以及所謂的調度程序上下文(已經提到)。 如果要將任何Spring bean注入Job,則必須在schedulerContext中顯式放置對該bean的引用:

@Configuration
class Scheduling {@Resourceval printer: Printer = null@Beandef schedulerFactory() = {val schedulerFactoryBean = new SchedulerFactoryBean()//...schedulerFactoryBean.setSchedulerContextAsMap(schedulerContextMap().asJava)//...schedulerFactoryBean}def schedulerContextMap() =Map("printer" -> printer)}

不幸的是,要注入作業的每個Spring bean必須在schedulerContextMap中明確引用。 更糟糕的是,如果您忘記了它,Quartz將在運行時以靜默方式記錄NPE。 將來,我們將編寫更強大的作業工廠。 但是對于初學者來說,我們已經準備好運行的Spring + Quartz應用程序,可以進行進一步的實驗,這些資源始終可以在我的GitHub帳戶下獲得。

您可能會問自己,我們不能簡單地使用MethodInvokingJobDetailFactoryBean嗎? 好吧,首先是因為它不適用于持久性作業存儲。 其次-由于無法將JobData傳遞給Job-因此我們無法再區分不同的作業運行。 例如,我們的作業打印消息將必須始終打印在該類中硬編碼的相同消息。

順便說一句,如果有人問您:Java企業開發人員需要多少個類才能打印“ Hello world!”。 您可以自豪地回答:4個類,30個JAR占用20 MiB的空間以及一個帶有10多個表的關系數據庫。 認真的說,這是本文的輸出……

參考: Java和社區博客上的JCG合作伙伴 Tomasz Nurkiewicz從Spring在JDBCJobStore中配置Quartz 。


翻譯自: https://www.javacodegeeks.com/2012/04/configuring-quartz-with-jdbcjobstore-in.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/373117.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/373117.shtml
英文地址,請注明出處:http://en.pswp.cn/news/373117.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

rlwrap插件,實現sqlplus上下翻頁

oracle在Linux下,sqlplus中不能上下翻,最主要我經常打錯字!嘿嘿 01、下載 RPM :http://rpmfind.net/linux/rpm2html/search.php?queryrlwrap tar.gz:https://fossies.org/linux/privat/rlwrap-0.42.tar.gz/ 百度云:h…

ice庫c語言例子,很不多的ICE架構入門學習例子

雖然使用傳統的SOCKET編程,我們可以更為清楚程序的性能,能夠更直接的操控SOCKET的設置,比如發送超時時間,接受BUFFER的大小,以及進行自己的協議加密。但是由于其調試成本較高,且不易于分布式部署ICE 作為一…

程序員的十個層次,你屬于哪一層?(轉)

自西方文藝復興以來,中國在自然科學方面落后西方很多,軟件領域也不例外。當然現在中國的許多程序員們對此可能有許多不同的意見,有些人認為中國的程序員水平遠落后于西方,有些則認為中國的程序員個人能力并不比西方的程序員差&…

操作系統基礎篇

程序運行的4個因素 (1).程序設計語言 (2).編譯系統 (3).操作系統 (4).指令集結構(硬件系統) 操作系統的定義:操作系統是掌控計算機上所有事情的軟件系統(硬件資源,軟件資源) 操作系統對內存,i/o,cpu&#x…

高效快速中值濾波算法c語言,快速中值濾波及c語言實現.docx

...快速中值濾波及c語言實現學生姓名: 劉 勇 學 號: 6100410218 專業班級: 數媒101【摘要】本文討論了用c語言在微機上實現中值濾波及快速算法,在程序設計的過程中充分考慮到程序運行的時間復雜度和空間復雜度的問題.解…

Arquillian 1.0.0.Final正式發布! 準備使用GlassFish和WebLogic! 殺死所有蟲子!

紅帽公司和JBoss社區今天宣布的1.0.0.Final發布的Arquillian ,其屢獲殊榮的建在Java虛擬機(JVM)運行測試平臺。 Arquillian大大減少了編寫和執行Java中間件集成和功能測試所需的工作。 它甚至使測試工程師能夠解決以前認為無法測試或測試成本…

Jquery選擇器特殊字符問題

場景: $("#" AAA ""),AAA代表某表單ID 當AAA為普通字符串時,ok; 當AAA含有特殊符號時(eg:a.b),獲取不到該對象; 原因:特殊符號會進行轉義&#xf…

qq五筆linux,QQ五筆 - 五筆小字典 QQ綁定很實用

九、 智能調頻、空碼檢索、詞序固定在QQ五筆中還有一些小亮點,比如它可以根據“最近輸入”、“輸入次數”對候選詞排序。同時為了加快檢索速度,默認只在常用字庫(GB2312)中檢索,只有出現空碼后才會繼續搜索容量更大的GBK字庫,很好…

DFS:C 小Y的難題(1)

解題心得: 1、在明確使用DFS之后一定要找到遞歸函數的出口、方向,以及遞歸的點(在某個情況下開始遞歸)(void 也可以return,但是沒有返回值)。遞歸時也要有遞歸的方向,最后都能夠達到遞歸的出口。 2、在DF…

使用ActiveMQ支持Spring Integration路由

正如我在上 一篇 文章中所討論的那樣 ,Spring Integration(SI) 是在Spring Framework之上構建的路由框架 ,它使您可以使用經過驗證的企業集成模式來通過消息傳遞解決系統集成問題。 配置好SI并執行路由和中介邏輯后,您…

quagga源碼分析--路由信息處理zebra-rib

對于各個協議生成的路由信息的處理屬于quagga中非常重要的一個功能,如何在內核進行路由增加,更新,刪除是一個復雜的過程。 quagga在thread任務調度中加入了一種工作隊列,work_queue,與內核的工作隊列類似,是…

android 關閉藍牙打電話功能,Android藍牙開發【八】hfp接聽、掛斷電話

繼續研究hfp相關功能。藍牙耳機可以控制手機接聽、拒接、掛斷電話,撥打電話等功能。本文主要分析下起這些操作的大致流程。在系統應用Bluetooth中com_android_bluetooth.cpp提供了多個回調方法,由hardware、協議棧回調過來。藍牙耳機的一些控制命令都會發…

android在listview中放入從sdcard讀取的bitmap

重寫viewbinder public class viewbinder_bookmark implements SimpleAdapter.ViewBinder{Overridepublic boolean setViewValue(View view, Object data, String textRepresentation){if(view instanceof ImageView && data instanceof Bitmap){ImageView imageview(I…

將狀態機模式實現為流處理器

在我的上一個博客中,我說我真的以為某些“四人行”(GOF)模式已經過時了,如果不是過時的話肯定不受歡迎。 特別是我說過StateMachine不是那么有用,因為您通常會想到另一種更簡單的方式來執行您正在執行的事情&#xff0…

android 自定義actionbar,如何讓android的actionbar浮動且透明

如上圖所示,谷歌地圖的actionbar是透明的,且浮動在整個布局之上,沒有占用布局空間。其實要做到這樣的效果,我們首先想到的是兩個方面:1.將讓actionbar浮動起來。2.給actionbar一個背景,可以為顏色也可以為圖…

CentOS 7安裝redis及php擴展

安裝remi源 # wget http://rpms.famillecollet.com/enterprise/remi-release-7.rpm # rpm -Uvh remi-release-7.rpm # sed -i -e "s/enabled1/enabled0/g" /etc/yum.repos.d/remi.repo 確認使用remi源時安裝的Redis版本。 安裝Redis 使用remi源yum安裝Redis。 # yum …

對Openshift上的Play Framework 2應用進行故障排除

Openshift故障排除 使用“ 自己動手”應用程序類型,您實際上可以有很大的自由度來支持幾乎可以在Linux機器上構建和運行的任何框架或服務器。 但是您必須做功課,并做一些研究。 因此,在本文中,我將向您展示一些我在使用Openshift和…

關于更換頭像的整個過程理解

之前我遇到一個問題,就是怎樣修改頭像,都沒有更改,后來把某個參數置為null,就解決了問題,但是知其然還要知其所以然,現在還是著重去梳理整個流程 頭像,需要關注的是3個變量: 本地地址…

Ajax與CustomErrors的尷尬

在ASP.NET程序中&#xff0c;為了給用戶顯示友好的錯誤信息&#xff0c;通常在web.config中進行如下的設置&#xff1a; <customErrors mode"RemoteOnly" defaultRedirect"/error/error.htm"> </customErrors> 但如果是一個ajax請求在服務端發…

JSF開發人員應該知道的5種有用方法

這篇文章的目的是總結一些JSF開發人員可以在日常工作中使用的便捷方法。 實用程序類是將所有方法放在一起的好地方。 我會稱此類為FacesAccessor。 第一種方法可能是最常用的方法。 它以給定名稱返回托管bean。 必須按faces-config.xml或注釋注冊該bean。 注入是好的&#xff0…