寫在前面:
前面有簡單的記錄下Timer定時的用法,但是在此次項目中,選擇的是quartz來完成定時操作任務的。兩者都可以完成定時操作,但是spring可以整合quartz,並且配置起來也比較簡便,還可以同時跑多個任務。就選擇了quartz,quartz的用法也很強大,這里也是簡單的記錄下。
第一步還是需要寫自己的任務類,如果有涉及到對數據庫的增刪改查操作,就按照正常的action,service ,dao的三層來編寫方法就好,只不過現在不是通過頁面發送請求來調用action,而是通過quartz的定時來調用action操作。
1.編寫自己的任務類:
@Controller("TimerTask") public class TimerTask { @Resource private ProjectWorkItemAssignmentService projectWorkItemAssignmentService; /** * 每天12:00去自動暫停ProjectWorkItemAssignment表中在執行的workItem * 以及去自動暫停WorkHoursRecord表中當天在執行的workItem */ public void autoPauseWorkItemOne() throws Exception{ projectWorkItemAssignmentService.autoPauseWorkItemOne(); } /** * 每天13:30去自動開啟ProjectWorkItemAssignment表中在執行的workItem * 以及去自動開啟WorkHoursRecord表中當天在執行的workItem */ public void autoStartWorkItem() throws Exception{ projectWorkItemAssignmentService.autoStartWorkItem(); } /** * 每天17:30去自動暫停ProjectWorkItemAssignment表中在執行的workItem * 以及去自動暫停WorkHoursRecord表中當天在執行的workItem */ public void autoPauseWorkItemTwo() throws Exception{ projectWorkItemAssignmentService.autoPauseWorkItemTwo(); } }
這里的任務類,我是當做action來寫的,然后里面的業務方法,根據自己的需求來即可,這里只是簡單的列舉一下子,后面對應的service,dao的業務就不具體上代碼了
2.編寫配置文件,這里我用到的是使用配置文件的形式來配置程序執行的周期以及頻率的(可以使用代碼的,自己下去查閱資料),由於spring可以整合quartz,還是挺方便的。
我們可以把quartz的配置寫在applicationContext.xml文件里面,也可以單獨拿出來寫一個,然后導入到applicationContext.xml文件中。這里就單獨寫一個文件。
applicationContext-quartz.xml(這里我自己配置了三個定時任務,可以根據自己的需要去開啟配置)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="TimerTask" /> <!-- 配置調度的定時任務 --> <property name="targetMethod" value="autoPauseWorkItemOne" /> <!-- 配置調度定時任務中的方法 --> <property name="concurrent" value="false" /> <!-- 是否並發執行 --> </bean> <bean id="jobDetail2" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="TimerTask" /> <!-- 配置調度的定時任務 --> <property name="targetMethod" value="autoStartWorkItem" /> <!-- 配置調度定時任務中的方法 --> <property name="concurrent" value="false" /> <!-- 是否並發執行 --> </bean> <bean id="jobDetail3" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="TimerTask" /> <!-- 配置調度的定時任務 --> <property name="targetMethod" value="autoPauseWorkItemTwo" /> <!-- 配置調度定時任務中的方法 --> <property name="concurrent" value="false" /> <!-- 是否並發執行 --> </bean> <!-- 觸發器 配置定時任務的調度的時間 --> <bean id="workItemTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail" ref="jobDetail" /> <property name="cronExpression"> <value>0 0 12 * * ? </value><!-- [秒] [分] [時] [日] [月] [年] 每天12點觸發--> </property> </bean> <bean id="workItemTrigger2" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail" ref="jobDetail2" /> <property name="cronExpression"> <value>0 30 13 * * ? </value><!-- [秒] [分] [時] [日] [月] [年] 每天13:30點觸發--> </property> </bean> <bean id="workItemTrigger3" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail" ref="jobDetail3" /> <property name="cronExpression"> <value>0 30 17 * * ? </value><!-- [秒] [分] [時] [日] [月] [年] 每天17:30點觸發--> </property> </bean> <!--定義調度器 --><!-- lazy-init='false'容器啟動就會執行調度程序 autowire="no"--> <bean id="workItemscheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" lazy-init="false" autowire="no"> <property name="triggers"> <list> <ref bean="workItemTrigger" /> <ref bean="workItemTrigger2" /> <ref bean="workItemTrigger3" /> </list> </property> </bean> </beans>
記得在spring的配置文件中加入quartz的配置文件
applicationContext.xml:
<import resource="classpath:configs/applicationContext-quartz.xml"/>
對於調用任務類有兩種方式,(使用JobDetailBean來調用某個類,)這里我用的是直接執行某個類的哪一個方法,比較方便。
其實在剛開始編寫的過程中也遇到各種問題,下面也簡單的記錄下。
當任務類是service層的類時,無法使用getCurrentSession()來獲取session,程序不報錯,直接卡在那里。然后是可以使用openSession()來重新打開一個session的,但是對於增刪改,每次都需要自己手動進行session的關閉以及事務的提交,不是很方便。當時一直沒有找到問題所在,為什么不可以使用getCurrentSession,雖然quartz是新開了一個線程,但是getCurrentSession()不是獲取當前線程的session,如果沒有就重新開一個么?為什么獲取不到呢?很是郁悶.......后來考慮到了是不是項目配置的session的生命周期有影響,因為項目延長了session的生命周期,如下:
<!-- 配置Spring的OpenSessionInViewFilter,以解決懶加載問題 --> <filter> <filter-name>OpenSessionInViewFilter</filter-name> <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class> </filter>
決定還是按照規矩來,不要把service層的類直接當任務類去調用,而是改用任務類為action,哇咔咔咔,竟然成功了,可以使用getCurrentSession來獲取session了,真的是折磨.....
所以寫代碼還是要多多試試,多多實踐下,然后在試的過程中一不小心就會給你大大的驚喜!!!
雖然記錄的很簡單,但是總比不記錄的要好,恩就這樣安慰自己,這個樣子也是很好的............................
補充一下一個獲取sessionFactory的方式:
WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext(); SessionFactory factory=wac.getBean(SessionFactory.class); Session session=factory.openSession();
在遇到問題的過程中也查閱了很多資料,https://blog.csdn.net/davaid_lee/article/details/44588577